标签:
C#异步编程_0
三种常见模式:1.async/await 2.Background类 3.BeginInvoke/EndInvoke
一、async/await
代码示例:
class Program { static void Main() { Task<int> value = DoAsyncStuff.Handing(5, 6); } } static class DoAsyncStuff { public static async Task<int> Handing(int i1, int i2) { int sum = await Task.Run(() => GetSum(i1, i2)); return sum; } public static int GetSum(int i1, int i2) { return i1 + i2; } }
异步方法有3中返回类型 1.void 2.Task 3.Task<T>
1.如果返回类型为void控制流退出。
2.如果返回类型为Task后续部分将设置Task的属性并退出
3.如果返回类型为Task<T>,后续部分将设置Task对象的Result属性并退出。
异步方法的控制流如下图所示:
await表达式:
await task ; task为一个异步执行的任务,为Task类型的对象;task为一个awaitable类型的实例,可以使用Task类来构建awaitable类型;
Task.Run(Func<TReturn> func); //可构建awaitable类型;
Func<TReturn>为一个不含任何参数,返回类型为TReturn的预定义委托。
如下代码所示:
public int Get10() //与Func<int>委托兼容 { return 10; } public async Task DoWorkAsync() { Func<int> ten = new Func<int>(Get10); int a = await Task.Run(ten); }
取消一个异步操作
CancellationToken、CancellationTokenSource ; //System.Threading.Tasks;
1.CancellationToken对象的任务需要定期检查其令牌(Token)的状态,如果其IsCancellationRequested属性为true,则操作停止并返回;
2.IsCancellationRequested属性设置为true后不可更改,类似一个开关程序;
3.CacellationTokenSource可调用Cancel方法,然后会将Cancellation的IsCancellationRequested属性设置为true;
CancellationTokenSoruce cts=new CancellationTokenSoruce(); CancellationToken token=cts.Token;
异步/同步等待任务完成
同步方法中等待任务完成:Task.WaitAll(); Task.WaitAny();
Task<int>[] tasks=new Task<int>[]{t1, t2 }; Task.WaitAll(tasks); Task.WaitAny(tasks);
异步方法中等待任务完成:Task.WhenAll(); Task.WaitAny();
List<Task<string>> tasks=new List<>(Task<string>); tasks.Add(t1); tasks.Add(t2); await Task.WhenAll(tasks);
二、BackgroundWorker类
BackgroundWorker类中主要用到的有这列属性、方法和事件:
重要属性:
1、CancellationPending 获取一个值,指示应用程序是否已请求取消后台操作。通过在DoWork事件中判断CancellationPending属性可以认定是否需要取消后台操作(也就是结束线程);
2、IsBusy 获取一个值,指示 BackgroundWorker 是否正在运行异步操作。程序中使用IsBusy属性用来确定后台操作是否正在使用中;
3、WorkerReportsProgress 获取或设置一个值,该值指示BackgroundWorker能否报告进度更新
4、WorkerSupportsCancellation 获取或设置一个值,该值指示 BackgroundWorker 是否支持异步取消。设置WorkerSupportsCancellation为true使得程序可以调用CancelAsync方法提交终止挂起的后台操作的请求;
重要方法:
1、CancelAsync 请求取消挂起的后台操作
2、RunWorkerAsync 开始执行后台操作
3、ReportProgress 引发ProgressChanged事件
重要事件:
1、DoWork 调用 RunWorkerAsync 时发生
2、ProgressChanged 调用 ReportProgress 时发生
3、RunWorkerCompleted 当后台操作已完成、被取消或引发异常时发生
另外还有三个重要的参数是RunWorkerCompletedEventArgs以及DoWorkEventArgs、ProgressChangedEventArgs。
BackgroundWorker bkWorker = new BackgroundWorker(); bkWorker.WorkerReportsProgress = true; bkWorker.WorkerSupportsCancellation = true; bkWorker.DoWork += new DoWorkEventHandler(DoWork); //bkWorker.ProgressChanged += new ProgressChangedEventHandler(ProgessChanged); bkWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CompleteWork); public void DoWork(object sender, DoWorkEventArgs e) { CreatWord(); } public void CompleteWork(object sender, RunWorkerCompletedEventArgs e) { Language.OfferLetterStatues = "报价书已完成!"; } public void CreatWord() { //CreatWord..... }
三、BeginInvoke. EndInvoke方法
如上所示为使用这一过程的三种标准模式。
1.当我们调用委托的BeginInvoke方法时,它开始在一个独立的线程执行引用方法,并且立即返回原始线程,原始线程可以继续,而引用方法会在线程池中的线程中并行执行。
2.当需要获取异步方法的结果时,可以检查BeginInvoke返回的IAsyncResult的IsCompleted属性,或调用委托的EndInvoke方法来等待委托完成。
BeginInvoke方法
delegate int MyDel(int first ,int second); class MyClass { static int Sum(int x,int y) { return x + y; } MyDel del = new MyDel(Sum); IAsyncResult iar = del.BeginInvoke(2, 4, null, null); }
方法参数:1.引用方法需要的参数;2.两个额外的参数---CallBack参数和State参数;
返回类型:返回给调用线程一个实现IAsyncResult接口的对象引用,这个接口包含线程池中线程运行异步方法的当前状态。
EndInvoke方法
EndInvoke方法用来获取由异步方法调用返回的值,并且释放线程使用的资源。具体特效如下:
方法参数:BeginInvoke方法返回的IAsyncResult对象的引用
返回类型:引用方法的返回值并将其作为方法的返回值
工作原理:1.如果线程池的线程已经退出,EndInvoke做如下事情:清理退出线程的状态并且释放其资源。返回引用方法的返回值
2.若果异步调用的线程仍在运行,调用线程就会停止并等待,直到清理完毕并返回值。
等待一直到完成模式(wait-until-done)
delegate int MyDel(int first,int second); class Program { static int Sum(int x,int y) { return x + y; } static void Main(string[] args) { MyDel del = new MyDel(Sum); IAsyncResult iar = del.BeginInvoke(3, 3, null, null); //开始异步调用 //同步方法中的 DoSomething..... int result = del.EndInvoke(iar); //等待结束并获取结果 } }
轮询模式(Polling)
工作原理:在轮询模式中,原始线程发起了异步方法的调用,做一些其他处理,然后使用IAsyncResult对象的IsComplete属性来定期检查开启的线程是否完成,如果异步方法已经完成,就调用EndInvoke,否则,它做一些其他处理,然后过一会再来检查。
delegate int MyDel(int first,int second); class Program { static int Sum(int x,int y) { return x + y; } static void Main(string[] args) { MyDel del = new MyDel(Sum); IAsyncResult iar = del.BeginInvoke(3, 3, null, null); //开始异步调用 while(!iar.IsCompleted) //检查异步方法是否完成 { Console.WriteLine("Not Done"); //同步方法中的 DoSomething..... } Console.WriteLine("Done"); int result = del.EndInvoke(iar); //等待结束并获取结果 } }
回调模式(CallBack)
工作原理:一旦初始线程发起了异步方法,它就自己管自己啦,不用再考虑同步方法,当异步方法调用结束之后,系统调用一个用户自定义的方法来处理结果,并且调用委托的EndInvoke方法,这个用户自定义的方法叫做回调方法
BeginInvoke的参数列表最后两个额外的参数由回调方法使用:
1.第一个参数callback,为回调方法的名字
2.第二个参数state,
回调方法:回调方法的参数和返回类型必须AsyncCallback委托类型形式一致,参数为IAsyncResult,返回类型为void;即 void AsyncCall(IAsyncResult iar);
回调方法内调用EndInvoke:在回调方法内,我们的代码应该调用委托的EndInvoke方法来处理异步方法执行后的输出值,需要调用委托的EndInvoke方法,我们肯定需要委托对象的引用,而委托在初始线程中,不在异步方法的线程中。
delegate int MyDel(int first,int second); class Program { static int Sum(int x,int y) { return x + y; } static void CallWhenDone(IAsyncResult iar) //回调方法 { AsyncResult ar = (AsyncResult)iar; MyDel del = (MyDel)ar.AsyncDelegate; //获取在其上调用异步调用的委托对象 int result = del.EndInvoke(iar); } static void Main(string[] args) { MyDel del = new MyDel(Sum); IAsyncResult iar = del.BeginInvoke(3, 3, CallWhenDone, null); //开始异步调用 while(!iar.IsCompleted) //检查异步方法是否完成 { Console.WriteLine("Not Done"); //同步方法中的 DoSomething..... } Console.WriteLine("Done"); int result = del.EndInvoke(iar); //等待结束并获取结果 } }
AsyncResult类
MSDN详解:https://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.asyncresult.aspx
参考博客:C# BeginInvoke与EndInvoke的使用
C#线程系列讲座(1):BeginInvoke和EndInvoke方法
VS2005中BackgroundWorker组件的使用经验
标签:
原文地址:http://www.cnblogs.com/hdtechnology/p/4931677.html