Task任务、多线程、异步调用返回值问题
在我们运用多线程,或者多任务作业时,有时候不可避免的会要的到某方法的运行结果,在这里总结任务、多线程和异步调用返回值问题。
先创建一个Task<TResult>对象,与Task的区别在于Task<TResult>对象有个TResult类型的返回值。创建完对象调用Start()方法,为了获取方法的返回值,要查询Task<TResult>对象的Result属性,如果任务还没有完成他的工作,结果则不可用,Result属性就会阻塞调用者。代码如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 Task<int> task = new Task<int>(() => Test());//创建任务 2 Taskw.Start();//开始任务 3 int result = Taskw.Result;//得到调用方法的结果 4 5 public int Test() 6 { 7 //方法体 8 }
异步调用返回结果我们必须用到IAsyncResult对象。首先我们通过委托调用需要异步执行的方法,在结束异步时,调用方法EndInvoke()方法得到委托方法的返回值。代码如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 private string[] MainTest() 2 { 3 weatherdelegate wd = new weatherdelegate(getResut); 4 IAsyncResult iresult = wd.BeginInvoke(null, null); 5 iresult.AsyncWaitHandle.WaitOne();//阻止当前线程,直到收到信号 6 string[] s = wd.EndInvoke(iresult); 7 iresult.AsyncWaitHandle.Close();//释放所有资源 8 return s; 9 } 10 11 //异步执行的方法 12 public string[] Test() 13 { 14 // 15 }
在多线程应用程序中提供和返回值是很复杂的,因此必须对某个过程的引用传递给线程类的构造函数,该过程不带参数也不返回值。
由于这些过程不能为函数也不能使用ByRef参数,因此从运行于不同线程的过程返回值是很复杂的。返回值的最简单方法是:使用BackgroundWorker组件来管理线程,在任务完成时引发事件,然后用事件处理程序处理结果。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class AreaClass2 2 { 3 public double Base; 4 public double Height; 5 public double CalcArea() 6 { 7 // Calculate the area of a triangle. 8 return 0.5 * Base * Height; 9 } 10 } 11 12 private System.ComponentModel.BackgroundWorker BackgroundWorker1 13 = new System.ComponentModel.BackgroundWorker(); 14 15 private void TestArea2() 16 { 17 InitializeBackgroundWorker(); 18 19 AreaClass2 AreaObject2 = new AreaClass2(); 20 AreaObject2.Base = 30; 21 AreaObject2.Height = 40; 22 23 // Start the asynchronous operation. 24 BackgroundWorker1.RunWorkerAsync(AreaObject2); 25 } 26 27 private void InitializeBackgroundWorker() 28 { 29 // Attach event handlers to the BackgroundWorker object. 30 BackgroundWorker1.DoWork += 31 new System.ComponentModel.DoWorkEventHandler(BackgroundWorker1_DoWork); 32 BackgroundWorker1.RunWorkerCompleted += 33 new System.ComponentModel.RunWorkerCompletedEventHandler(BackgroundWorker1_RunWorkerCompleted); 34 } 35 36 private void BackgroundWorker1_DoWork( 37 object sender, 38 System.ComponentModel.DoWorkEventArgs e) 39 { 40 AreaClass2 AreaObject2 = (AreaClass2)e.Argument; 41 // Return the value through the Result property. 42 e.Result = AreaObject2.CalcArea(); 43 } 44 45 private void BackgroundWorker1_RunWorkerCompleted( 46 object sender, 47 System.ComponentModel.RunWorkerCompletedEventArgs e) 48 { 49 // Access the result through the Result property. 50 double Area = (double)e.Result; 51 MessageBox.Show("The area is: " + Area.ToString()); 52 }
更多关于多线程返回值参见http://technet.microsoft.com/zh-cn/magazine/wkays279(VS.90).aspx和http://msdn.microsoft.com/zh-cn/library/wkays279(v=vs.100).aspx
自此推荐一篇学习多线程和异步调用的文章http://www.cnblogs.com/panjun-Donet/articles/1133627.html