转换异步/等待到Task.ContinueWith

编程入门 行业动态 更新时间:2024-10-24 21:28:06
本文介绍了转换异步/等待到Task.ContinueWith的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

此问题是由评论这个触发:

如何备份端口非线性异步/计谋 code到.NET 4.0没有 Microsoft.Bcl.Async ?

How to back-port a non-linear async/await code to .NET 4.0 without Microsoft.Bcl.Async?

在链接的问题,我们有一个的WebRequest 运行,我们要重新尝试的次数有限,如果它不断失败。该异步/计谋 code可能是这样的:

In the linked question, we have a WebRequest operation we want to retry for a limited number of times, if it keeps failing. The Async/await code could look like this:

async Task<HttpWebResponse> 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 ,因为像这样(未经测试):

From the first thought, I'd use TaskCompletionSource, as something like this (untested):

Task<HttpWebResponse> GetResponseWithRetryAsync(string url, int retries) { if (retries < 0) throw new ArgumentOutOfRangeException(); var request = WebRequest.Create(url); var tcs = new TaskCompletionSource<HttpWebResponse>(); Action<Task<WebResponse>> 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 ?

The question is, how to do this without TaskCompletionSource?

推荐答案

我已经找到了如何做到这一点,而不异步/计谋或 TaskCompletionSource ,使用嵌套任务和 Task.Unwrap 代替。

I've figured out how to do it without async/await or TaskCompletionSource, using nested tasks and Task.Unwrap instead.

首先,为解决@ mikez的评论,这里的 GetResponseAsync 实施.NET 4.0:

First, to address @mikez's comment, here's GetResponseAsync implementation for .NET 4.0:

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

现在,这里的 GetResponseWithRetryAsync 实施

static Task<HttpWebResponse> GetResponseWithRetryAsync(string url, int retries) { if (retries < 0) throw new ArgumentOutOfRangeException(); var request = WebRequest.Create(url); Func<Task<WebResponse>, Task<HttpWebResponse>> proceedToNextStep = null; Func<Task<HttpWebResponse>> 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(); }

这是一个有趣的练习。它的工作原理,但我认为它的方式更加难走,比异步/计谋版本。

更多推荐

转换异步/等待到Task.ContinueWith

本文发布于:2023-11-09 09:59:21,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1572084.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Task   ContinueWith

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!