Csharp/C#教程:将async / await转换为Task.ContinueWith分享


将async / await转换为Task.ContinueWith

这个问题是由对这个问题的评论引发的:

如何在没有Microsoft.Bcl.Async情况下将非线性async/await代码反向移植到.NET 4.0?

在链接的问题中,我们有一个WebRequest操作,如果它一直失败,我们想要重试有限次数。 Async/await代码可能如下所示:

 async Task GetResponseWithRetryAsync(string url, int retries) { if (retries < 0) throw new ArgumentOutOfRangeException(); var request = WebRequest.Create(url); while (true) { WebResponse task = null; try { task = request.GetResponseAsync(); return (HttpWebResponse)await task; } catch (Exception ex) { if (task.IsCanceled) throw; if (--retries == 0) throw; // rethrow last error // otherwise, log the error and retry Debug.Print("Retrying after error: " + ex.Message); } } } 

从第一个想法,我使用TaskCompletionSource ,就像这样(未经测试):

 Task GetResponseWithRetryAsync(string url, int retries) { if (retries < 0) throw new ArgumentOutOfRangeException(); var request = WebRequest.Create(url); var tcs = new TaskCompletionSource(); Action<Task> proceesToNextStep = null; Action doStep = () => request.GetResponseAsync().ContinueWith(proceedToNextStep); proceedToNextStep = (prevTask) => { if (prevTask.IsCanceled) tcs.SetCanceled(); else if (!prevTask.IsFaulted) tcs.SetResult((HttpWebResponse)prevTask.Result); else if (--retries == 0) tcs.SetException(prevTask.Exception); else doStep(); }; doStep(); return tcs.Task; } 

问题是, 如何在没有TaskCompletionSource情况下执行此TaskCompletionSource

我已经想出了如何在没有async/awaitTaskCompletionSource使用嵌套任务和Task.Unwrap来做到这Task.Unwrap

首先,要解决@ mikez的评论,这里是.NET 4.0的GetResponseAsync实现:

 static public Task GetResponseTapAsync(this WebRequest request) { return Task.Factory.FromAsync( (asyncCallback, state) => request.BeginGetResponse(asyncCallback, state), (asyncResult) => request.EndGetResponse(asyncResult), null); } 

现在,这里是GetResponseWithRetryAsync实现:

 static Task GetResponseWithRetryAsync(string url, int retries) { if (retries < 0) throw new ArgumentOutOfRangeException(); var request = WebRequest.Create(url); Func, Task> proceedToNextStep = null; Func> doStep = () => { return request.GetResponseTapAsync().ContinueWith(proceedToNextStep).Unwrap(); }; proceedToNextStep = (prevTask) => { if (prevTask.IsCanceled) throw new TaskCanceledException(); if (prevTask.IsFaulted && --retries > 0) return doStep(); // throw if failed or return the result return Task.FromResult((HttpWebResponse)prevTask.Result); }; return doStep(); } 

这是一项有趣的练习。 它的工作原理,但我认为它比async/await版更难以理解。

上述就是C#学习教程:将async / await转换为Task.ContinueWith分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/1000910.html

(0)
上一篇 2021年12月28日
下一篇 2021年12月28日

精彩推荐