2013-04-18 58 views
2

我有這樣的代碼:與UI交談的線程?

private void buttonStart_Click(object sender, EventArgs e) 
{ 
    Task.Factory.StartNew(() => GeneraListaCartelle()) 
     .ContinueWith(t => GeneraListaCartelleCompletata() 
     , CancellationToken.None 
     , TaskContinuationOptions.None 
     , TaskScheduler.FromCurrentSynchronizationContext()); 
} 

private void GeneraListaCartelle() 
{ 
    try 
    { 
     ... some operation .... 
    } 
    catch (Exception err) 
    { 
     txtErrors.AppendText(err.Message); 
    } 
} 

GeneraListaCartelleCompletata() 
{ 
    ... process finished... 
} 

txtErrors是 「主」 線程(UI)。當我發現錯誤時,異步線程無法寫入UI控件,並且我得到一個invalid cross-thread exception

我可以使用線程內的UI進行對話嗎?

+0

您使用的是WPF還是WinForms? – 2013-04-18 07:05:24

+3

什麼樣的應用程序,winform或WPF,如果WinForm尋找[MethodInvoker](http://msdn.microsoft.com/en-us/library/system.windows.forms.methodinvoker.aspx),爲WPF,尋找[Dispatcher.Invoke](http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke.aspx) – Habib 2013-04-18 07:05:42

+0

我正在使用WinForm,對不起;) – markzzz 2013-04-18 07:09:37

回答

3

如果你是靶向然後WinForm應用程序:

try 
    { 
     ... some operation .... 
    } 
catch (Exception err) 
    { 
     if (txtErrors.InvokeRequired) 
     { 
      txtErrors.BeginInvoke(new MethodInvoker(
       delegate { txtErrors.AppendText(err.Message); }) 
       ); 
     } 
    } 
4

如果您正在使用的WinForms,你將需要調用你的方法在UI線程像

catch (Exception err) 
{ 
    if(this.InvokeRequired){ 
     Action<Exception> act = ((ex) => { 
      txtErrors.AppendText(ex.Message); 
     }); 
     this.Invoke(act, new object[] { err }); 
    } 
    else{ 
     txtErrors.AppendText(err.Message); 
    } 
} 

如果您正在使用WPF你將需要

catch (Exception err) 
{ 
    if(this.Dispatcher.CheckAccess()){ 
     txtErrors.AppendText(err.Message); 
    } 
    else { 
      Action<Exception> act = ((ex) => { 
      txtErrors.AppendText(ex.Message); 
      }); 
     this.Dispatcher.Invoke(act, new object[] { err }); 
    } 
} 
2

有來自msdn一個例子:

// This delegate enables asynchronous calls for setting 
// the text property on a TextBox control. 
delegate void SetTextCallback(string text); 

// This method demonstrates a pattern for making thread-safe 
// calls on a Windows Forms control. 
// 
// If the calling thread is different from the thread that 
// created the TextBox control, this method creates a 
// SetTextCallback and calls itself asynchronously using the 
// Invoke method. 
// 
// If the calling thread is the same as the thread that created 
// the TextBox control, the Text property is set directly. 
private void SetText(string text) 
{ 
    // InvokeRequired required compares the thread ID of the 
    // calling thread to the thread ID of the creating thread. 
    // If these threads are different, it returns true. 
    if (this.textBox1.InvokeRequired) 
    { 
     SetTextCallback d = new SetTextCallback(SetText); 
     this.Invoke(d, new object[] { text }); 
    } 
    else 
    { 
     this.textBox1.Text = text; 
    } 
} 
1

集CheckForIllegalCrossThreadCalls假的叫Form_Load事件處理程序

1

拉這一個老項目,我不得不處理從另一個線程更新UI的。也應該爲你工作。

delegate void addtoValProg(); 
addtoValProg myDelegate; 

myDelegate = new addtoValProg(invokeControl); 

private void GeneraListaCartelle() 
{ 
    try 
    { 
     //... some operation .... 
    } 
    catch (Exception err) 
    { 
     invokeControl(); 
    } 
} 

private void invokeControl() 
{ 
    if (this.InvokeRequired) 
    { 
     this.Invoke(this.myDelegate); 
    } 
    else 
    { 
     txtErrors.AppendText(err.Message); 
     txtErrors.Update(); 
    } 
}