系列目录:
1.委托和事件绑定
2.泛型委托
3.委托和多线程
委托跟多线程
最常用的情况,我们的一个界面程序,里面有一个耗时操作.我们开辟一个新的线程来计算耗时方法,但是出现一个问题:新的线程计算完成后如果想要更新界面UI,程序会报错:"属于另一个线程没有权限访问主程序",不是原话但大概是这个意思吧.这次,责任又落到委托身上了. 怎么处理?
解决方案应该是这样的.
1.UI线程定义一个委托
2.UI线程启动耗时线程,并将委托以参数形式是传递给耗时线程计算方法.可以理解传递了指向方法的指针
3.耗时线程计算完成后,执行委托方法更新UI界面.
简单说就是虽然耗时线程不能直接操作UI线程的方法,但是可以用委托啊.虽然过程是上面的过程,但是C#可不是这么写的哦,微软又又把这个过程简化了.委托的调用Invoke方法,还有一个BeginInvoke方法,它们的区别就是Invoke是同步的,BeginInvoke是异步的,BeginInvoke是开启一个新的线程运算委托方法.
BeginInvoke必须要和EndInvoke进行配合,EndInvoke是必须的,如果耗时线程没有完成就执行EndEnvoke,UI线程会等待耗时线程完成.
BeginInvoke方法触发你的异步方法,它和你想要执行的异步方法有相同的参数。另外还有两个可选参数,第一个是AsyncCallback委托是异步完成的回调方法。第二个是用户自定义对象,该对象将传递到回调方法中。BeginInvoke立即返回并且不等待完成异步的调用(继续执行该下面的代码,不需要等待)。BeginInvoke返回IAsyncResult接口,可用于检测异步调用的过程。
下面代码演示使用BeginInvoke和EndInvoke进行异步回调的方式。
public sealed partial class MyPage1 : Page
{
public delegate string MyDelegate(int x,int y);
MyDelegate addDelegate;
AsyncCallback callback;
public MyPage1()
{
this.InitializeComponent();
addDelegate = new MyDelegate((x, y) => {
return (x + y).ToString();
});
callback = new AsyncCallback(DelegateCompleted);
//计算10+10,回掉函数callback,传递本身的对象
var result = addDelegate.BeginInvoke(10, 10, callback, addDelegate);
}
public void DelegateCompleted(IAsyncResult iar)
{
//因为BeginInvoke传递了addDelegate对象
//这里iar.AsyncState就是addDelegate
//直接使用EndInvoke获取结果
string result =(iar.AsyncState as MyDelegate).EndInvoke(iar);
}
}
有上面可以看出,委托起了很关键的作用.但是委托加多线程的这种写法依然觉得很麻烦.计算进度完成可获取结果,基本方式大概就几种
1.不断的查询进度,完成后调用EndInvoke
2.定义回调函数,在回调函数内部EndInvoke
3.Begin之后直接EndInvoke,放弃异步同步等待.
详细请参考:https://www.cnblogs.com/wolf-sun/p/5675791.html
每种方法写法都比较繁琐.但使用Task任务语法就不一样了,Task任务可以使用强大的async/await关键字进行异步等待.关于Task/async~await之后会进一步介绍.