【问题标题】:How to correctly implement a TAP method?如何正确实现 TAP 方法?
【发布时间】:2022-03-17 20:26:41
【问题描述】:

我想提供一种基于任务的异步模式样式方法。在等待方法时,我找不到这两种提供方法的方式有什么区别:

// GetStats is a delegate for a void method in this example
public Task GetStatsAsync()
{
    return Task.Run(GetStats);
}

public async Task GetStatsAsync()
{
    return await Task.Run(GetStats);
}

// Usage:
await GetStatsAsync();
// Difference?

上面的方法似乎比下面的方法开销少。在查看 MSDN 博客时,我注意到他们似乎使用了 lower 方法。 (例如this article

为什么?究竟有什么区别?它们似乎都有效。

【问题讨论】:

  • 您可能需要编辑您的问题并将TaskEx 替换为Task,因为这就是现在众所周知的方式。
  • @Varvara Kalinina 完成

标签: c# .net async-await task-parallel-library


【解决方案1】:

这两个在逻辑上是相同的,但第二个开销更大,因此不推荐。

您可以找到我的async intro helpful,以及task based asynchronous pattern document

有关async 开销的更多信息,我推荐Zen of Async by Stephen Toub

您可能还想阅读"Should I Expose Asynchronous Wrappers for Synchronous Methods?" 简而言之,答案是“不”。

【讨论】:

  • 第一个也不推荐!让调用者选择是否要在线程池上运行。仅仅在其中放一个 Task.Run 并不能使算法神奇地非阻塞。
  • 他们确实使用第一个示例中的 Run 方法来报告进度 (int processCount = await Task.Run<int>(() =>)。
  • 你是对的。 MSDN 示例代码没有达到应有的效率。
  • 对于那些对最后一个链接(现在已断开)感到好奇的人:devblogs.microsoft.com/pfxteam/…
  • @Beltway:谢谢!我更新了帖子。几年前,MS 更改了所有他们的博客链接,并且由于某种原因没有进行转发...
【解决方案2】:

我的印象是实现 TAP 模式的正确方法如下:

  public Task<IResult> GetLongWindedTaskResult(){
          var tcs = new TaskCompletionSource<IResult>();
            try
            {
               tcs.SetResult(ResultOFSomeFunction());
            }
            catch (Exception exp)
            {
                tcs.SetException(exp);
            }
            return tcs.Task;
}

这种方式可确保您在抛出异常时正确获取异常,并且在需要时更容易实现取消方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 2010-09-21
    • 2015-06-11
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    相关资源
    最近更新 更多