Invoke,BeginInvoke,EndInvoke
Posted 试看将来的环球,必将是代码的世界。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Invoke,BeginInvoke,EndInvoke相关的知识,希望对你有一定的参考价值。
(一)使用规则
public IAsyncResult BeginInvoke(Delegate method);
public IAsyncResult BeginInvoke(Delegate method, params object[] args);
①:传递一个委托
this.BeginInvoke(new InvokeMethod(InvokeXXX), new object[] { listDgv });
public delegate void InvokeMethod(object x);
public void InvokeXXX(object x)
{
dgvMain.DataSource = x;
}
②:传递系统委托 public delegate void Action<T>(T obj)
this.BeginInvoke(new Action
③:传递匿名委托
④:传递无参委托
this.BeginInvoke(new Action(()=>{
progressBar1.Value = 0;
}));
(二)BeginInvoke,EndInvoke在异步线程中的应用
2.1 线程概述
在操作系统中一个进程至少要包含一个线程,然后,在某些时候需要在同一个进程中同时执行多项任务,或是为了提供程序的性能,将要执行的任务分解成多个子任务执行。这就需要在同一个进程中开启多个线程。我们使用C#编写一个应用程序(控制台或桌面程序都可以),然后运行这个程序,并打开windows任务管理器,这时我们就会看到这个应用程序中所含有的线程数,如下图所示。
**:如果任务管理器没有“线程数”列,可以【查看】>【选择列】来显示“线程计数”列。从上图可以看出,几乎所有的进程都拥有两个以上的线程。从而可以看出,线程是提供应用程序性能的重要手段之一,尤其在多核CPU的机器上尤为明显。
2.2 用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程
在C#中使用线程的方法很多,使用委托的BeginInvoke和EndInvoke方法就是其中之一。BeginInvoke方法可以使用线程异步地执行委托所指向的方法。然后通过EndInvoke方法获得方法的返回值(EndInvoke方法的返回值就是被调用方法的返回值),或是确定方法已经被成功调用。我们可以通过四种方法从EndInvoke方法来获得返回值。
关于BeginInvoke函数的分析:
**:在❶处有一个AsyncCallback的委托,该委托的定义为:public delegate void AsyncCallback(IAsyncResult ar),因此异步回调函数要以这个委托来进行签名调用。
BeginInvoke方法可启动异步调用。它与您需要异步执行的方法具有相同的参数,另外它还有两个可选参数。第一个参数是一个AsyncCallback 委托,该委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象可向回调方法传递信息。BeginInvoke立即返回,不等待异步调用完成。BeginInvoke会返回IAsyncResult,这个结果可用于监视异步调用进度。
关于EndInvoke函数的分析:
EndInvoke方法检索异步调用的结果。调用BeginInvoke后可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。EndInvoke的参数包括您需要异步执行的方法的out和ref参数以及由BeginInvoke返回的IAsyncResult。
当我们Main()中加入Thread.Sleep(15000);等待15钟,再调用BeginInvoke(),任务管理器中线程数的变化如下图:说明在调用BeginInvoke()后系统会创建一个线程。
2.3 BeginInvoke和EndInvoke非阻塞式操作线程
如下图所示有这样一个UI,在执行某个耗时操作时,同时要在界面显示耗时操作运行的时间以告知终端用户。
代码实现
代码分析:
(三)异步调用的异常处理过程。如下图产生的异常错误信息提示到终端用户。
代码实现
参考资料:
如何:对 Windows 窗体控件进行线程安全调用 https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/ms171728(v=vs.100)
以上是关于Invoke,BeginInvoke,EndInvoke的主要内容,如果未能解决你的问题,请参考以下文章
C#中Control的Invoke和BeginInvoke是相对于支线线程