2009-08-04 78 views
20

我有一个基于对话框的应用程序,我将其中的I/O操作读写委托给不同的线程。BeginInvoke和Thread.Start之间的区别

我只是想明确的是有两种方法之间有什么区别..

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

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

第二种方法:

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

我注意到的BeginInvoke挂在UI进行了第二,而第二种方法不..

请帮忙

+4

有关信息,请明确说明您是否指Control.BeginInvoke和Delegate.BeginInvoke;我相信你的意思是第一个,但他们几乎是完全相反的,所以区别很重要。 – 2009-08-04 09:34:32

+0

它是第一种方法(Control.BeginInvoke),因为我在表单上执行此操作。 – 2009-08-04 09:42:27

回答

17

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

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

进一步阅读文章here

0

区别在于BeginInvoke方法只是在SAME线程上异步调用委托。

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

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

+1

更好的性能是一个假设...有一个线程,你将遇到旧的CrossThreadedExceptions ... – Pondidum 2009-08-04 09:31:14

8

BeginInvokes通过在窗口中发布消息,在UI线程上异步执行委托(这就是为什么会挂起UI)。如果委托中的代码访问用户界面,那就是你需要做的事情。

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

3

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

Control.BeginInvoke在该控件所属的线程上运行该方法。如果您当前位于控件的线程中,则只有在将控制权返回给消息循环时才会运行该方法,例如,退出你的事件处理器。

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标志并锁定它。

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

利奥Bruzzaniti

1

正如其他已经公布,Thread.Start将推出一个新的线程,如果你想改变一个字段的值Control.BeginInvoke()将运行在UI线程上的代码(必要的,例如)。

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

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

下面是更详细的how-to article

相关问题