BeginInvoke和Thread.Start之间的区别

时间:2009-08-04 09:17:28

标签: c# .net multithreading delegates

我有一个基于对话框的应用程序,我将把I / O操作读写委托给不同的线程。

我只是想澄清两种方法之间有什么区别..

第一种方法:(我这样做,我的主要形式-Form.cs)

delegate void Action();
Action _action = new Action(Method);
this.BeginInvoke(_action);

第二种方法:

Thread th = new  Thread( new ThreadStart(_action));
th.Start();

我注意到BeginInvoke挂起UI一秒钟,而第二种方法却没有..

请帮忙

6 个答案:

答案 0 :(得分:17)

BeginInvoke会将操作发布到与Form相同的线程上的消息泵的消息队列中,它不会创建新的线程。

Control.BeginInvoke的行为类似于异步线程启动,但有重要的内部差异。

详细阅读文章here

答案 1 :(得分:8)

BeginInvokes通过向窗口发布消息,在UI线程上异步执行委托(这就是它挂起UI的原因)。如果委托中的代码访问UI,则需要执行此操作。

Thread.Start的方法在一个新的,独立的线程上执行委托。

答案 2 :(得分:3)

Thread.Start在您的新Thread上运行。

Control.BeginInvoke在Control所属的线程上运行该方法。如果您当前在控件的线程上,则在将控制权返回到消息循环之前,该方法不会运行,例如,退出你的事件处理程序。

答案 3 :(得分:3)

试试这个。

class Form1: Form
{
   public void ButtonWasClicked(object sender, EventArgs e)
   {
       /* Call the UI's Invoke() method */
       this.Invoke((MethodInvoker)delegate()
       {
           /* Stuff to do.. you can access UI elements too without
            * the nasty "Control accessed from another thread.."
            * Use BeginInvoke() only if you have code after this section
            * that you want the UI to execute without waiting for this 
            * inner blockto finish. 
            */
       });
   }
}

关于BeginInvoke(),它被使用,因此函数将立即返回,下一行将被执行,依此类推,等等,而无需等待方法完成。

不同之处在于,如果您创建一个线程,您将对其进行更多控制,就像任何其他线程一样。您将遇到CrossThreadExceptions!而如果使用IAsyncResult和BeginInvoke(),则无法控制异步操作​​的执行流,因为它由运行时管理。

通过调用,您还可以向方法发送更多参数,并在操作完成后调用方法。

MyDelegateWithTwoParam del = new MyDelegateWithTwoParam(_method);
AsyncCallback callback = new AsyncCallback(_callbackMethod);
IAsyncResult res = del.BeginInvoke(param1, param2, callback, null);

private void _callbackMethod(IAsyncResult iar) {
   /* In this method you can collect data that your operation might have returned.
    * If MyDelegateWithTwoParam has a return type, you can find out here what i was. */
}

我已广泛用于UI开发。我会更多地将线程用于类似服务的对象。 (想象一下保留和侦听TCP连接的对象)和用于UI背后工作的异步方法(也可以查看BackgroundWorker)。 如果第一种方法需要额外的秒来启动,请不要担心:Thread.Abort()不是 永远是你最好的解决方案。在您的流程代码中尝试_abort标志并将其锁定。

希望我已经回答了这个问题。

Leo Bruzzaniti

答案 4 :(得分:1)

正如其他人发布的那样,Thread.Start将启动一个新线程,而Control.BeginInvoke()将在UI线程上运行代码(例如,如果你想改变一个字段的值,则是必需的)。

但是,我发现在WinForms中执行后台任务的最简单方法是使用BackgroundWorker。将它放到表单上,连接事件,然后调用RunWorkerAsync()。然后在DoWork事件中编写后台任务。任何UI刷新都可以放在RunWorkerCompleted事件中。

使用BackgroundWorker可以避免所有恼人的线程处理和IsInvokeRequired。

以下是更详细的how-to article

答案 5 :(得分:0)

不同之处在于BeginInvoke方法只是在SAME线程上异步调用委托。

使用Thread.Start,您将创建一个完全不同的线程。

Thread.Start肯定会给你更好的表现!