马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
TAP 是基于任务的异步模式,在 .NET Framework 4 中引入。TAP取代了 APM 和EAP,是推荐的异步编程模式。
async / await
async 和 await 是为异步编程提供的语法糖,方便我们快捷编写异步代码。关键字 async 作用仅仅是为了能够使用 await 关键字以及怎么处理返回值。await 关键字可以想象成 asynchronous wait,在awaitable 完成之前,异步方法会等待,但线程不会堵塞。- public async Task DoSomethingAsync()
- {
- // For this example, we`re just going to (aynchronously) wait 100ms.
- await Task.Delay(100);
- }
复制代码对于调用方法,await 声明了一个挂起点,等异步方法结束后会捕获当前上下文继续执行后续代码。、
awaitable
await 就像是一元操作符,接收一个参数 - awaitable. Task 和 Task 都是这样的类型。- public async Task NewStuffAsync()
- {
- // Use await and have fun with the new stuff.
- await ...
- }
- public Task MyOldTaskParallelLibraryCode()
- {
- // Note that this is not an async method, so we can`t use await in here.
- ...
- }
- public async Task ComposeAsync()
- {
- // We can await Tasks, regardless of where they come from.
- await NewStuffAsync();
- await MyOldTaskParallelLibraryCode();
- }
复制代码 Task.Yield()
await Task.Yield() 方法来强制异步完成方法,可以让我们更好的控制异步方法的执行。如果当前任务很耗时,并且优先级比较低,可以考虑在方法开始的时候加上 await Task.Yield() ,让系统去调度其他更需要的任务,稍后再来完成该耗时任务。- static async Task Process()
- {
- await Task.Yield();
- var tcs = new TaskCompletionSource<bool>();
- Task.Run(() =>
- {
- Thread.Sleep(1000);
- tcs.SetResult(true);
- });
- tcs.Task.Wait();
- }
复制代码我不着急,我到后面从新排队去,你先去处理其他任务吧。其实是利用 await 实现线程的切换。
Task.ConfigureAwait
默认情况,异步方法结束后会捕获和回复当前上下文。如果你不关系延续上下文,可以使用 Task.ConfigureAwait 指示不要回复而是继续执行等待的任务。- await someTask.ConfigureAwait(continueOnCapturedContext:false);
复制代码 CancellationTokenSource
从 .NET Framework 4 开始,TAP 方法支持取消操作。- var cts = new CancellationTokenSource();
- string result = await DownloadStringTaskAsync(url, cts.Token);
- … // at some point later, potentially on another thread
- cts.Cancel();
- // 取消多个异步调用
- var cts = new CancellationTokenSource();
- IList<string> results = await Task.WhenAll(from url in urls select DownloadStringTaskAsync(url, cts.Token));
- // at some point later, potentially on another thread
- …
- cts.Cancel();
复制代码 Progress
通过 Progress 可以监控异步方法的执行进度。- private async void btnDownload_Click(object sender, RoutedEventArgs e)
- {
- btnDownload.IsEnabled = false;
- try
- {
- txtResult.Text = await DownloadStringTaskAsync(txtUrl.Text,
- new Progress<int>(p => pbDownloadProgress.Value = p));
- }
- finally { btnDownload.IsEnabled = true; }
- }
复制代码 Task.Run
Task.Run() 方法可以很方便的将耗时任务放到线程池上执行。- public async void button1_Click(object sender, EventArgs e)
- {
- // 默认恢复上下文
- textBox1.Text = await Task.Run(() =>
- {
- // … do compute-bound work here
- return answer;
- });
- }
- public async void button1_Click(object sender, EventArgs e)
- {
- // 内部使用 await
- pictureBox1.Image = await Task.Run(async() =>
- {
- using(Bitmap bmp1 = await DownloadFirstImageAsync())
- using(Bitmap bmp2 = await DownloadSecondImageAsync())
- return Mashup(bmp1, bmp2);
- });
- }
复制代码 Task.FromResult
Task.FromResult 用来创建一个带返回值的,已完成的 Task。- public Task<int> GetValueAsync(string key)
- {
- int cachedValue;
- return TryGetCachedValue(out cachedValue) ?
- Task.FromResult(cachedValue) : // 如果本地有缓存,直接以同步的方式获取(但返回的是异步结果)
- GetValueAsyncInternal(); // 如果本地没有key对应的缓存,则异步从远端获取
- }
- // 异步方法从远端获取缓存
- private async Task<int> GetValueAsyncInternal(string key)
- {
- …
- }
复制代码 Task.WhenAll
异步等待 一组异步操作的完成。- Task [] asyncOps = (from addr in addrs select SendMailAsync(addr)).ToArray();
- try
- {
- await Task.WhenAll(asyncOps);
- }
- catch(Exception exc)
- {
- foreach(Task faulted in asyncOps.Where(t => t.IsFaulted))
- {
- … // work with faulted and faulted.Exception
- }
- }
复制代码 Task.WhenAny
一组异步操作中,第一个异步操作完成时返回。
- 可以同时进行多个相同的异步操作,选择最快完成的那个
- // 从多个行情源处获取行情,使用最快的那个
- var cts = new CancellationTokenSource();
- var recommendations = new List<Task<bool>>()
- {
- GetBuyRecommendation1Async(symbol, cts.Token),
- GetBuyRecommendation2Async(symbol, cts.Token),
- GetBuyRecommendation3Async(symbol, cts.Token)
- };
- Task<bool> recommendation = await Task.WhenAny(recommendations);
- cts.Cancel(); // 取消剩余任务
- if (await recommendation) BuyStock(symbol);
复制代码- List<Task<Bitmap>> imageTasks =
- (from imageUrl in urls select GetBitmapAsync(imageUrl)
- .ContinueWith(t => ConvertImage(t.Result)).ToList();
- while(imageTasks.Count > 0)
- {
- try
- {
- Task<Bitmap> imageTask = await Task.WhenAny(imageTasks);
- imageTasks.Remove(imageTask);
- Bitmap image = await imageTask;
- panel.AddImage(image);
- }
- catch{}
- }
复制代码 Task.Delay
在异步方法中暂定一段时间。 可以和 Task.WhenAny ,Task.WhenAll 结合使用以实现超时处理。- public async void btnDownload_Click(object sender, EventArgs e)
- {
- btnDownload.Enabled = false;
- try
- {
- Task<Bitmap> download = GetBitmapAsync(url);
- if (download == await Task.WhenAny(download, Task.Delay(3000)))
- {
- Bitmap bmp = await download;
- pictureBox.Image = bmp;
- status.Text = "Downloaded";
- }
- else
- {
- pictureBox.Image = null;
- status.Text = "Timed out";
- var ignored = download.ContinueWith(
- t => Trace("Task finally completed"));
- }
- }
- finally { btnDownload.Enabled = true; }
- }
复制代码 公众号 - 希夏普
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |