线程安全调用Winform控件

kar*_*hul 2 c# winforms

参考文献:http: //msdn.microsoft.com/en-us/library/ms171728.aspx http://stackoverflow.com/questions/5408155/how-to-make-delegate-thread-sta

我想创建一个新的线程并使其成为STA因此我无法使用异步委托或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.
   }

}
Run Code Online (Sandbox Code Playgroud)

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

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

如果UpdateUIControls正在主UI线程中执行,那么应该没有prblem,对吧?所以,我想我的问题的答案真的取决于问题1.

如果有人分享他/她的智慧,我将不胜感激

Karephul

Mar*_*ell 6

控件具有线程亲和力; 你只能通过他们的创建线程安全地与他们交谈.

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

oneOfMyControls.Invoke(del [, args]);
Run Code Online (Sandbox Code Playgroud)