首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何做Task.ContinueWith<Task>(.)

如何做Task.ContinueWith<Task>(.)
EN

Stack Overflow用户
提问于 2019-02-08 08:27:31
回答 3查看 305关注 0票数 0

我使用HttpClient,我想写这样的东西:

代码语言:javascript
复制
HttpClient client = ...;
Task<string> getContent()
{
    return client.GetAsync(...)
   .ContinueWith( t => t.Result.Content.ReadAsStringAsync() );
}

我知道我能写

代码语言:javascript
复制
.ContinueWith( t => t.Result.Content.ReadAsStringAsync().Result);

但是池的一个线程会被阻塞。我要continueWithTask和Google任务库一样。

我怎样才能做到呢?

更新

是的,我确实需要使用任务而不是异步/等待,我很清楚我想要什么。

UPDATE2

我修改了我的观点,现在我认为我选择技术是错误的。如果有人怀疑,这里是一个好代码的伟大的例子

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-02-08 08:31:02

现在,您应该避免使用ContinueWith,除非您有非常具体的原因,否则您更倾向于使用async/await;我怀疑这样做会奏效:

代码语言:javascript
复制
async Task<string> getContent()
{
    var foo = await client.GetAsync(...); // possibly with .ConfigureAwait(false)
    return await foo.Content.ReadAsStringAsync(); // possibly with .ConfigureAwait(false)
}
票数 6
EN

Stack Overflow用户

发布于 2019-02-08 15:13:37

是的,我确实需要使用任务而不是异步/等待,我很清楚我想要什么。

我强烈推荐马克的回答。我想不出为什么不使用async/await,除非您被困在Windows4.0(即Windows )上。情况不可能是这样,因为您使用的是HttpClientTask.Run。因此,请记住,这个答案纯粹是指导性的,不推荐生产。

ContinueWith调用可以是“链式”的,类似于Promise.then在JavaScript中的工作方式,但是开箱即用的C#链接语义比JavaScript的更尴尬。

首先,Task<Task<T>>类型不是自动展开的。有一个可用的Unwrap方法。另一方面,.Result的使用--一种更自然地与ContinueWith一起使用的TPL遗留物--将异常包装在AggregateException中,这可能会导致一种有趣的“级联”,在这种情况下,您的内部异常可以被深入地隐藏在嵌套的AggregateException实例中。因此,AggregateException.Flatten的存在,以纠正后的混乱-事实.哦,你应该去ContinueWith

这是第一次尝试,显式地指定TaskScheduler,使用Unwrap来打开嵌套任务,并通过使用GetAwaiter().GetResult()而不是Result来避免嵌套异常

代码语言:javascript
复制
Task<string> getContent()
{
  // I am so sorry, future coder, but I cannot use await here because <insert good reason>
  return Task.Run(()=> client.GetAsync(...))
      .ContinueWith(t => t.GetAwaiter().GetResult().Content.ReadAsStringAsync(), TaskScheduler.Default).Unwrap()
      .ContinueWith(t => t.GetAwaiter().GetResult(), TaskScheduler.Default);
}

如果您在代码中经常这样做,您可能需要使用封装了一些逻辑的.Then。哦,一定要在评论中写个道歉;即使未来的维护者是你自己,这也是与这样的代码相关的礼貌之处。;)

票数 3
EN

Stack Overflow用户

发布于 2019-02-08 12:42:06

但是池的一个线程将被阻塞

情况并非如此,因为只有在“先行”任务完成后才会调用ContinueWith委托。Result不会阻塞,它甚至是免费的同步。

然而,第二个.Result (ReadAsStringAsync().Result)正在阻塞。所以你必须把它变成另一个ContinueWith

一般来说,一个顺序的IOs序列会变成一个ContinueWith序列。

一般来说,await在这里是可取的,但是您表示这对您不起作用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54588462

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档