【C# Task】TaskCompletionSource
TaskCompletionSource具体功能
用于封装一个没有不带委托的任务实列。可以在其他线程控制该任务实列什么时候结束、取消、错误。类似于EventWaitHandle的功能。
属性
Task
方法
- SetCanceled:将TaskCompletionSource.Task 转换为Cancel状态。
- SetException:将TaskCompletionSource.Task 转换为Faluted状态。
- SetResult:将TaskCompletionSource.Task 转换为RanToCompletion状态。
- TrySetCanceled
- TrySetException
- TrySetResult
TaskCompletionSource应用
TaskCompletionSource :表示未绑定委托的 Task 的制造者方,并通过 Task 属性提供对使用者方的访问。
由TaskCompletionSource创建的任务的状态是由TaskCompletionSource上的方法显式控制的。
TaskCompletionSource的所有成员都是线程安全的,可以在多个线程中并发使用。
https://blog.csdn.net/Czhenya/article/details/120442315
1、 使用 TaskCompletionSource 实现暂停功能
案例:火车票选购>选好车票>支付(软件界面暂停)>跳到支付页面>支付成功( 支付页面继续执行)>跳到支付页面
简单的使用例子如下,有两个方法在两个不同的线程,此时在 A 线程调用 A 方法,而在 B 线程调用 B 方法。在A方法等待任务完成才继续往下走,而在 B 方法则设置任务完成
TaskCompletionSource<bool> tcs = new(); Task.Run(async () => await ChoiceTicket(tcs)); Task.Run(async () => await PayForMoney(tcs)); Console.Read(); //选择车票 static async Task<bool> ChoiceTicket(TaskCompletionSource<bool> tcs) { Console.WriteLine("选购火车票") ; Console.WriteLine("跳转到到支付页面"); await tcs.Task; Console.WriteLine("订票完成"); return tcs.Task.Result; } //选择支付页面 static async Task PayForMoney(TaskCompletionSource<bool> tcs) { await Task.Delay(3000).ContinueWith((t) => Console.WriteLine("选购支付宝支付")); tcs.SetResult(true); Console.WriteLine("支付完成"); Console.WriteLine("跳到火车票软件完成"); }
通过控制台可以看到先输出 A 开始 然后等待一秒输出 B 开始 之后调用了 SetResult 方法,然后输出 A 完成 也就是 A 方法在 await taskCompletionSource.Task 等待直到 B 调用 taskCompletionSource.SetResult(true) 方法才继续往下
2、将回调(事件)封装为任务完成源
作用:使得代码更容易阅读和维护
事件完成后调用回调方法
在之前的指南中,我们讨论了生成图像的应用程序;假设您需要应用程序将这些图像上传到某个地方。假设有一个名为"MyBox"的云文件存储服务,它有一个.NET库,上传文件的库方法如下:
public static void UploadFile(string name, byte[] data, Action<bool> onCompleted);
查阅库的文档后,您会发现onCompleted是在上载完成时调用的回调,如果上载成功,则值为true,如果上载失败,则值为false。若要使用此库方法上载文件,必须执行如下操作,前提是您的应用程序具有可显示名为statusText的文本的内容:
public async void OnUploadButtonClicked() { statusText.Text = "Generating Image..."; byte[] imageData = await GenerateImage(); statusText.Text = "Uploading Image..."; MyBox.UploadFile("image.jpg", imageData, success => { statusText.Text = success ? string.Empty : "Error Uploading"; }); }
修改成TaskCompletionSource
public static Task<bool> UploadFile(string name, byte[] data) { var taskCompletionSource = new TaskCompletionSource<bool>(); try { MyBox.UploadFile(name, data, success => { taskCompletionSource.SetResult(success); }); } catch (Exception ex) { taskCompletionSource.SetException(ex); } return taskCompletionSource.Task; }
public async void OnUploadButtonClicked() { statusText.Text = "Generating Image..."; byte[] imageData = await GenerateImage(); statusText.Text = "Uploading Image..."; bool success = await MyBoxHelper.UploadFile("image.jpg", imageData); statusText.Text = success ? string.Empty : "Error Uploading"; }
像同步一样写代码。简直不要太爽。