2011-03-30 111 views
2

参考文献: http://msdn.microsoft.com/en-us/library/ms171728.aspx http://stackoverflow.com/questions/5408155/how-to-make-delegate-thread-sta线程安全调用WinForm的控制

我想创造一个新线程,使因此,我无法使用异步委托或BackgroudWorker(如参考文献链接1中所述)。因此,我最终创建了一个自己的线程,使其成为STA并附加一个回调来了解任务何时完成。该代码是类似下面,即使我现在用的调用需要,我仍然得到InvalidOperationException异常(在一段时间一次)


delegate UpdateEventHander(Object sender, EventArgs e); 
class MyTask{ 
    // to generate an event 
    public event UpdateEventHandler Finished; 
    public void Start(){ 
     Result = // something that require the thread to be STA. 
     Finished(this, EventArgs.Empty); 
    } 
    public Result GetResult(){ 
     return Result; 
    } 
} 

Class Foo : Form{ 
    // It has many UI Controls obviously 
    public void doSomething(){ 
     MyTask task = new MyTask(); 
     task.Finished += new UpdateEventHander(CompletionHandler); 
     Thread thread = new Thread(new ThreadStart(task.Start)); 
     thread.setAppartmetnState(AppartmentState.STA); 
     thread.start(); 
    } 
    public void CompletionHandler(Object sender, EventArgs e){ 
     MyTask task = (MyTask) sender; 
     if (oneOfMyControls.InvokeRequired){ 
     delegateToUpdateUIconrols del = new delegateToUpdateUIconrols(updateUIControls); 
     del.invoke(); 
     }else{ 
     UpdateUIControls(); 
     } 
    } 
    public delegate void delegateToUpdateUIconrols(); 
    public void UpdateUIControls(){ 
     // It updates UI controls 
     // Datagrid view value properties like backgroud color and stuff. 
     // change text in the label. 
    } 

} 

问题1:哪些线程将UpdateUIControls执行? - 如果你说“Main UI Thread” - 那么在那种情况下系统将如何知道它是否应该在Main UI中运行而不是其他线程?当我调用invoke()时,我没有传递任何引用(关于主UI线程)..所以invoke()在技术上在同一线程上执行..

问题2:一旦偶尔,我得到InvalidOperationException。正是这一个 http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/6b450a21-e588-414a-afae-9adabfd03674/

如果UpdateUIControls在主UI线程中执行,应该没有问题,对不对?所以,我想回答我的问题实际上取决于问题1.

如果有人分享这个

Karephul他/她的智慧,我会很高兴

回答

6

控制有线程亲和力;你只能从他们的创建线程中安全地与他们交谈。

您正在检查InvokeRequired;但是,您正在使用Control.Invoke(在UI线程上运行)混合Delegate.Invoke(在当前线程上运行);意义非常不同。它应该是:

oneOfMyControls.Invoke(del [, args]); 
+0

aaahh,让我试试那个......你说的话肯定有道理。 – karephul 2011-03-30 21:42:40

+0

只是一个后续问题:我可以在任何控件上调用这个委托,它会在主线程中执行(并且可能更新其他控件)?基本上,委托执行依赖于控制我执行调用? – karephul 2011-03-30 21:47:12

+0

我看到你更新了你的asnwer以及..标记你的答案是正确的。谢谢 – karephul 2011-03-30 21:55:49