简体   繁体   English

任务FromResult与TaskCompletionSource SetResult

[英]Task FromResult vs TaskCompletionSource SetResult

What is the difference concerning the functionality and meaning of the 有关功能和含义的区别是什么

TaskCompletionSource + SetResult vs Task + FromResult TaskCompletionSource + SetResult vs Task + FromResult

in the SendAsync method? 在SendAsync方法?

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    if (request.RequestUri.Scheme != Uri.UriSchemeHttps)
    {
        var response = new HttpResponseMessage(HttpStatusCode.Forbidden) {ReasonPhrase = "HTTPS Required"};
        var taskCompletionSource = new TaskCompletionSource<HttpResponseMessage>();
        taskCompletionSource.SetResult(response);
        return taskCompletionSource.Task;
    }
    return base.SendAsync(request, cancellationToken);
}

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    if (!request.RequestUri.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
    {
        HttpResponseMessage reply = request.CreateErrorResponse(HttpStatusCode.BadRequest, "HTTPS is required for security reason.");
        return Task.FromResult(reply);
    }

    return base.SendAsync(request, cancellationToken);
}

Task.FromResult was a new addition in .NET 4.5. Task.FromResult是.NET 4.5中的新增功能。 It is a helper method that creates a TaskCompletionSource and calls SetResult. 它是一个帮助方法,它创建一个TaskCompletionSource并调用SetResult。 If you are using .NET 4 or earlier you will have to use SetResult. 如果您使用的是.NET 4或更早版本,则必须使用SetResult。

If all you want is to return a completed Task<TResult> with a result (or a completed Task without one), simply use Task.FromResult . 如果你想要的只是返回一个已完成的Task<TResult>结果(或没有一个完成的Task ),只需使用Task.FromResult

Task.FromResult is a simple tool to create a finished task with a result. Task.FromResult是一个使用结果创建已完成任务的简单工具。 TaskCompletionSource is a much more robust tool that supports everything. TaskCompletionSource是一个更强大的工具,支持一切。 You can set exceptions, return a non-completed task and set it's result later and so forth 您可以设置例外,返回未完成的任务并稍后设置结果,依此类推

PS: It seems like you're trying to "fake" async methods by returning a finished task. PS:看起来你正试图通过返回完成的任务来“伪造”异步方法。 Although that's the best way to do it, make sure "faking" async is really what you want to accomplish. 虽然这是最好的方法,但要确保“假装”异步确实是你想要完成的。

I'm fairly sure that Task.FromResult() does something very similar under the cover. 我很确定Task.FromResult()在封面下做了类似的事情。

A better use case scenario for TaskCompletionSource is when you implemented multithreading yourself. TaskCompletionSource一个更好的用例场景是你自己实现多线程。 In that scenario, you immediately return an awaitable task, whose result is not set until the background thread finishes and calls either TaskCompletionSource.SetResult() or TaskCompletionSource.SetException() . 在这种情况下,您立即返回一个等待的任务,在后台线程完成并调用TaskCompletionSource.SetResult()TaskCompletionSource.SetException()之前,其结果不会设置。

I believe Task.FromResult() is more efficient, but you could also do the following, which is more readable, IMO: 我相信Task.FromResult()更有效率,但您也可以执行以下操作,它更具可读性,IMO:

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    if (request.RequestUri.Scheme != Uri.UriSchemeHttps)
        return new HttpResponseMessage(HttpStatusCode.Forbidden) {ReasonPhrase = "HTTPS Required"};
    return await base.SendAsync(request, cancellationToken);
}

You can still override the base's virtual SendAsync , because async doesn't change the method signature. 您仍然可以覆盖基础的虚拟SendAsync ,因为async不会更改方法签名。

Task.FromResult is a convenient method to create a Task for a synchronous method. Task.FromResult是为同步方法创建任务的便捷方法。 Although a Task represents an asynchronous operation, not all Tasks are actually asynchronous and may just be simple wrappers for synchronous methods. 尽管Task表示异步操作,但并非所有Tasks实际上都是异步的,并且可能只是同步方法的简单包装器。

If you use Task.FromResult, then please include in your documentation that your method is not a 'real' asynchronous method but a syntactic cube of sugar. 如果您使用Task.FromResult,那么请在您的文档中包含您的方法不是“真正的”异步方法,而是糖的语法立方体。 This shall inform the caller not to expect asynchronous behavior from it. 这将通知调用者不要期望它的异步行为。

On the other hand, if you want to manually create an asynchronous function, please use the SetResult or TrySetResult methods of TaskCompletionSource as described here . 在另一方面,如果你想手动创建一个异步函数,请使用的setResultTrySetResult TaskCompletionSource的方法所述在这里

Regardless of the version of your .NET framework, always use TaskCompletionSource instead of Task.FromResult to create real asynchronous functions. 无论.NET框架的版本如何,始终使用TaskCompletionSource而不是Task.FromResult来创建真正的异步函数。

Sources: 资料来源:

  1. Task.FromResult Task.FromResult
  2. Internal Constructor of Task 任务的内部构造函数
  3. TaskCompletionSource.SetResult TaskCompletionSource.SetResult
  4. TaskCompletionSource.TrySetResult TaskCompletionSource.TrySetResult

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM