我有一个基于对话框的应用程序,我将把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一秒钟,而第二种方法却没有..
请帮忙
答案 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肯定会给你更好的表现!