2012-06-12 341 views
0

在这里,我在C#中使用简单的逻辑。我从两个DateTimePicker s中减去天数,并生成与总天数相同的GridView行。我把这个逻辑放在一个Timer中,它的间隔为100毫秒,并自动执行。这适用于90-100行,但如果它变为1000行,那么程序会卡住。所以,我想我需要使用线程。我怎样才能做到这一点?我知道基本的多线程,并试图这样,没有工作:多线程的GridView更新

private void timer1_Tick(object sender, EventArgs e) 
{ 
    myMethod(); 
} 

void myMethod() { 
    ed_Picker.MinDate = sd_Picker.Value; 
    TimeSpan ts = new TimeSpan(); 

    //GridView.Rows.cont 

    label3.Text = ed_Picker.Value.CompareTo(sd_Picker.Value).ToString(); 
    //dateTimePicker2.MinDate = dateTimePicker1.Value; 

    ts = ed_Picker.Value.Subtract(sd_Picker.Value); 
    double d; 

    d = Math.Ceiling(ts.TotalDays) + 1; 
    label3.Text = d.ToString(); 
    DataGridViewRow row = new DataGridViewRow(); 


    GridView.RowCount = Int32.Parse(d.ToString()); // This is key line which I like to put in new Thread 
    for (int i = 1; i <= GridView.RowCount; i++) 
    { 
     GridView.Rows[i - 1].Cells[0].Value = sd_Picker.Value.AddDays(Convert.ToDouble(i - 1)).ToLongDateString(); 
     GridView.Rows[i - 1].Cells[0].ReadOnly = true; 
    } 
    DateTimeConverter dtc = new DateTimeConverter(); 
    TimeSpan ts1 = new TimeSpan(); 

    try 
    { 
     for (int i = 0; i < GridView.RowCount; i++) 
     { 
      ts1 += Convert.ToDateTime(GridView.Rows[i].Cells[2].Value).Subtract(Convert.ToDateTime(GridView.Rows[i].Cells[1].Value)); 
     } 
    } 
    catch (Exception ex) 
    { 

    } 

    label6.Text = ts1.ToString(); 
} 
+3

你想做什么?这个故事可以帮助我们理解情节。无论哪种方式,你应该阅读关于BackgroundWorkers [这里](http://www.dotnetperls.com/backgroundworker)和[这里](http://msdn.microsoft.com/en-us/library/cc221403(v = VS.95)的.aspx)。 – SimpleVar

+0

好的,我想创建新的线程所以,即使有10K行,它也要干扰主程序,并在场景后面运行。 –

+0

@YoryeNathan:我试图使用Bcakgroundworkers,但得到相同的错误:“InvalidOperationException - 跨线程操作无效:控制'ed_Picker'从其创建的线程以外的线程访问。 myMethod方法的第一行出现此错误。 –

回答

0

下面是如何使用BackgroundWorker的做线程的工作和更新UI的总体思路:如果

var worker = new BackgroundWorker {WorkerReportsProgress = true}; 
worker.DoWork += this.ThreadWorkMethod; 
worker.ProgressChanged += this.ThreadProgressMethod; 
worker.RunWorkerAsync(); 

... 

private void ThreadWorkMethod(object sender, DoWorkEventArgs e) 
{ 
    var worker = (BackgroundWorker)sender; 

    for (int i = 0; i = 1000; i++) 
    { 
     // Time consuming operation 
     Thread.Sleep(1000); 

     worker.ReportProgress(i * 100d/1000, i); 
    } 
} 

private void ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    // Here you can access controls, etc. 

    if (e.Progresspercentage == 100) 
    { 
     this.progLabel.Text = "100% Done"; 
    } 
    else 
    { 
     this.progLabel.Text = string.Format("{0}% ({1}/1000)", 
              e.ProgressPercentage, 
              e.UserState); 
    } 
} 

而且你也想收听RunWorkerCompleted事件 - 你也可以从那里访问控件,等等。

所以DoWork方法是所有关于做硬线程工作,并调用ReportProgress,以便它可以适当地更改UI,每当需求来了。当DoWork方法完成(返回或结束)时,RunWorkerCompleted事件将被自动调用。