2012-06-08 26 views
2

我有一个C#.NET WinForms应用程序使这个异步调用:BeginInvoke的回调函数

simpleDelegate.BeginInvoke(null, null); 

我的功能正在被代表呼吁,所有的伟大工程。问题是,在工作线程完成函数之后,我需要主线程来更新我的winform上的一些控件。如果工作者线程尝试更新这些控件,.NET会吓坏了。但是我需要主线程保持对用户操作的响应,然后在工作线程完成调用异步函数之后调用我的函数UpdateFormAfterServerCall()。

如果你能给我一个简洁的代码示例,而不是抽象地解释如何做到这一点,我将不胜感激。我已经阅读了一百个解释,并且只是无法正确地将它们连接在一起。

注:BeginInvoke的之前我有:

simpleDelegate = new MethodInvoker(CallServer); 

回答

3

从不同的线程,如果你想更新其被另一个线程使用拥有GUI MethodInvoker

if(control.InvokeRequired) 
control.Invoke((MethodInvoker) (()=> updating_function())); 
else 
updating_function(); 
+0

这工作完美!谢谢!!! – HerrimanCoder

1

Control类(FormControl以及)具有Invoke方法,你可以从任何线程调用此向GUI线程上执行代码。

此外,Control有一个方便的InvokeRequired属性,通知您是否您已经在GUI线程。你可以例如在表单创建以下方法:

public class MyForm 
{ 
    // ... 
    public void UpdateMe() 
    { 
     if (InvokeRequired) 
     { 
      Invoke(new Action(UpdateMe)); 
      return; 
     } 

     // Code to update the control, guaranteed to be on the GUI thread 
    } 
} 
+0

谢谢...但我很困惑。您在UpdateMe中调用UpdateMe。这不会造成无限循环吗?什么应该调用UpdateMe,以及如何在我的工作线程中运行的函数完成后触发该函数被调用? – HerrimanCoder

+0

'InvokeRequired'只有在UI线程以外的其他线程上执行时才为真,并且'Invoke'在UI线程上执行'UpdateMe'。基本上它说“if(notOnUiThread){executeMeOnUIThread(); return;}”。这样你就可以从你的工作线程调用'UpdateMe'而不必担心在UI线程上工作。 –

0

你可以使用一个BackgroundWorker

BackgroundWorker bw = new BackgroundWorker(); 

string result = null; 

bw.DoWork += (s, e) => 
{ 
    // Executes on background thread. 
    // UI remains responsive to user activity during this time. 
    result = CallServer(); 
}; 

bw.RunWorkerCompleted += (s, e) => 
{ 
    // Executes on UI thread upon completion. 
    resultTextBox.Text = result; 
}; 

bw.RunWorkerAsync(); 
+0

我试过你的代码,我仍然得到了关于不能从工作线程更新的控件的错误。你的代码应该在哪里生活?在哪个功能?它是否在工作线程或主线程中执行? – HerrimanCoder

+0

上面的代码应该从UI线程运行,通常在一些事件处理程序中运行。 'BackgroundWorker'将首先在工作线程上执行'DoWork'委托,允许UI保持响应;完成后,它将在UI线程上执行'RunWorkerCompleted'。 – Douglas