2012-06-12 536 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事件將被自動調用。