2012-08-13 40 views
0

我一直在努力實現一個BackgroundWorker到我的應用程序,到目前爲止,還沒有順利。在一個新線程中,我想打開一個新的表單,該表單將包含一個進度條和一個標籤以報告進度,但是,這樣做效果不佳。當我調用ShowDialog時,應用程序不再響應。這是因爲我的代碼是從我的Form1運行的,而且我正在顯示WorkingForm?此外,這可以實施更清潔?的BackgroundWorker的ShowDialog導致應用程序停止

private void button14_Click(object sender, EventArgs e) 
{ 
    List<object> param = new List<object>(); 
    object[] objectparams = new object[1]; 
    objectparams[0] = null; 
    Opera opera = new Opera(); 
    System.Reflection.MethodInfo clearOpera = opera.GetType().GetMethod("ClearOpera"); 
    param.Add(clearOpera); 
    param.Add(opera); 
    param.Add(objectparams); 
    backgroundWorker1.RunWorkerAsync(param); 
} 

private void button2_Click_1(object sender, EventArgs e) 
{ 
    Browser.cancelPending = true; 
} 
private delegate void getnewform(); 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    mainForm main = new mainForm(); 
    TestURLGUI4.Form1 form = (TestURLGUI4.Form1)Application.OpenForms[0]; 
    var variab = (bool)form.Invoke(new getnewform(main.AskForConfirmation)); 
     List<object> param = e.Argument as List<object>; 

     List<object> result = new List<object>(); 
     var method = param[0] as MethodInfo; 
     object[] parameters = param[2] as object[]; 
     if (parameters[0] == null) 
     { 
      result.Add(method.Invoke(param[1], null)); 
      result.Add(false); 
     } 
     else 
     { 
      result.Add(method.Invoke(param[1], parameters)); 
      if (parameters.Contains(true)) 
       result.Add(true); 
     } 
     int progress = (100 * Browser.progressValue)/Browser.progressMax; 

     backgroundWorker1.ReportProgress(progress); 

     // If the BackgroundWorker.CancellationPending property is true, cancel 
     if (backgroundWorker1.CancellationPending) 
     { 
      Console.WriteLine("Cancelled"); 
      Browser.cancelPending = true; 
     } 
     e.Result = result; 
} 

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
     TestURLGUI4.WorkingForm form = (TestURLGUI4.WorkingForm)Application.OpenForms[1]; 
     form.progressBar1.Value = e.ProgressPercentage; 

     form.label1.Text = Browser.progressValue + "/" + Browser.progressMax; 
     Application.DoEvents(); 
} 

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    List<object> param = e.Result as List<object>; 
    if (e.Cancelled == false && param.Contains(true)) 
    { 
     Display.DisplayURLs(param[0] as SortableBindingList<URL>); 
     TestURLGUI4.WorkingForm form = (TestURLGUI4.WorkingForm)Application.OpenForms[1]; 
     MessageBox.Show("Done"); 

    } 
    else if (e.Cancelled == false && param.Contains(false)) 
    { 
     TestURLGUI4.WorkingForm form = (TestURLGUI4.WorkingForm)Application.OpenForms[1]; 
     MessageBox.Show("Done"); 
    } 


} 

    public class mainForm 
{ 
public void AskForConfirmation() 
{ 
    TestURLGUI4.Form1 form = (TestURLGUI4.Form1)Application.OpenForms[0]; 
    var workingForm = new TestURLGUI4.WorkingForm(); 
    workingForm.ShowDialog(form); 
    workingForm.DialogResult = DialogResult.None; 

} 
} 

編輯: 好吧,我已經根據建議更新了我的代碼,而現在,這將產生在System.Windows.Forms.dll中一個stackoverflowexception:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    mainForm main = new mainForm(); 
    TestURLGUI4.Form1 form = (TestURLGUI4.Form1)Application.OpenForms[0]; 
     List<object> param = e.Argument as List<object>; 
     List<object> result = new List<object>(); 
     var method = param[0] as MethodInfo; 
     object[] parameters = param[2] as object[]; 
     if (parameters[0] == null) 
     { 
      result.Add(method.Invoke(param[1], null)); 
      result.Add(false); 
     } 
     else 
     { 
      result.Add(method.Invoke(param[1], parameters)); 
      if (parameters.Contains(true)) 
       result.Add(true); 
     } 
     int progress = (100 * Browser.progressValue)/Browser.progressMax; 

     backgroundWorker1.ReportProgress(progress); 

     // If the BackgroundWorker.CancellationPending property is true, cancel 
     if (backgroundWorker1.CancellationPending) 
     { 
      Console.WriteLine("Cancelled"); 
      Browser.cancelPending = true; 
     } 
     e.Result = result; 


} 

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    TestURLGUI4.Form1 form1 = (TestURLGUI4.Form1)Application.OpenForms[0]; 
    if (Application.OpenForms.Count >= 2) 
    { 
     TestURLGUI4.WorkingForm form2 = (TestURLGUI4.WorkingForm)Application.OpenForms[1]; 
     form2.progressBar1.Value = e.ProgressPercentage; 

     form2.label1.Text = Browser.progressValue + "/" + Browser.progressMax; 
     Application.DoEvents(); 
    } 
    else if(Application.OpenForms.Count == 1) 
    { 
     var workingForm = new TestURLGUI4.WorkingForm(); 
     workingForm.ShowDialog(form1); 
    } 
} 
+0

讓youyr生活輕鬆了許多。在您關閉線程之前進行確認,並完全消除Application.OpenForms的需求。這是一個幾乎保證的比賽,表格可能會在您獲得參考後關閉。甚至不想考慮一下你的顯式索引索引可能會在應用程序發生一些變化之後留下來。 – 2012-08-13 21:15:43

+0

有人可以看看我更新的代碼嗎? – 2012-08-14 01:17:26

回答

4

BackgroundWorker的目的是調用另一個線程(而不是UI線程)上的代碼。通過在DoWork方法中調用Invoke,您完全可以規避BackgroundWorker的目的。在啓動工作人員之前,完成所有UI的工作。如果您需要與工人正在工作的用戶交互,這樣做在ProgressChanged處理程序 - 它運行在UI線程上,你不需要ProgressChanged使用Invoke

通過調用DoWork UI的工作,你運行一個死鎖的風險,這將掛程序

0

你不能上運行的UI其他線程。必須在主線程上。

實例化UI啓動新線程之前。在新線程中,您想要使用的控件上使用跨線程調用方法。看這裏例如http://msdn.microsoft.com/en-us/library/ms171728.aspx

+1

除非你打算建議一個實際的解決方案,否則這會更好地發佈爲評論。 – ChrisF 2012-08-13 20:24:19

相關問題