Task
类表示产生类型为T的值的正在进行的工作。我想知道Task.FromResult方法的必要性是什么?
也就是说,在已经拥有生成的值的情况下,为什么需要将其重新包装到任务中?
唯一想到的是它被用作其他接受Task实例的方法的适配器。
Task
类表示产生类型为T的值的正在进行的工作。我发现有两种常见的使用情况:
Task.FromResult
,并且客户端异步等待网络 I/O。这样,您可以使用 ChannelFactory
共享客户端/服务器之间的相同接口。 - Nelson RothermelIEnumerable<T>
继承自 IDisposable
- 它允许可枚举类型具有可释放资源,而不是强制其这样做。FromResult
、async
和 await
都不会生成线程。 - Stephen ClearyTask
的方法意味着“可能是异步的”。因此,有时会给方法一个异步签名,明确知道某些实现将是同步的(例如,NetworkStream应该是异步的,而MemoryStream应该是同步的)。 - Stephen Cleary一个例子是使用缓存的方法。如果已经计算出结果,可以使用Task.FromResult
返回一个带有值的完成任务。如果没有计算出结果,则返回表示正在进行工作的任务。
Task.FromResult
返回的任务,可以被缓存。 - Paulo MorgadoTask.FromResult(0)
、Task.FromResult(1)
、Task.FromResult(false)
和Task.FromResult(true)
都被缓存了。你不应该缓存一个用于网络访问的任务,但从结果中返回一个任务是完全可以的。你更喜欢每次需要返回值时创建一个新的任务吗? - Paulo Morgado当您想要创建一个可等待的方法,但不想使用 async 关键字时,可以使用它。我找到了这个例子:
public class TextResult : IHttpActionResult
{
string _value;
HttpRequestMessage _request;
public TextResult(string value, HttpRequestMessage request)
{
_value = value;
_request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage()
{
Content = new StringContent(_value),
RequestMessage = _request
};
return Task.FromResult(response);
}
}
在这里,您正在创建自己的IHttpActionResult接口实现,以在Web Api动作中使用。 ExecuteAsync方法应该是异步的,但您不必使用async关键字使其异步和可等待。由于您已经拥有结果并且不需要等待任何内容,因此最好使用Task.FromResult。
当您需要进行异步操作,但有时候结果是同步处理的时候,请使用Task.FromResult。您可以在此处找到一个很好的示例http://msdn.microsoft.com/en-us/library/hh228607.aspx。
Task.FromResult
用于获取先前缓存的异步结果。 - Rodrigo ReisTask.Run() 创建一个 lambda 线程,不需要 async 并返回一个类型对象。在我的示例中,我有多个任务同时运行等待它们的完成。一旦所有任务都完成了,我就可以循环遍历它们的结果。Task.FromResult 用于推送由 Task.Run() 未生成的任务结果。
在这种情况下,Task.FromResult 推送一个类型对象,即 Result 类中的 RecordStruct 类。我创建了两个调用函数 getData 的任务。Task.WaitAll 处理每个任务并将结果推送到类型为 RecordStruct 的 result 对象数组中。然后,我作为结果访问 RecordStruct 类的属性元素。
public class RecordStruct
{
public RecordStruct(string _element) {
element = _element;
}
public string element { get;set; }
}
public class TaskCustom
{
public Task<RecordStruct> getData(string phrase)
{
if (phrase == "hello boise")
{
return Task.FromResult(new RecordStruct("Boise is a great place to live"));
}
return Task.Run(() =>
{
return new RecordStruct(phrase);
});
}
}
[Fact]
public async Task TestFactory()
{
TaskCustom obj = new TaskCustom();
List<Task<RecordStruct>> tasks = new List<Task<RecordStruct>>();
tasks.Add(obj.getData("hello world"));
tasks.Add(obj.getData("hello boise"));
Task.WaitAll(tasks.ToArray());
for(int ctr = 0; ctr < tasks.Count; ctr++) {
if (tasks[ctr].Status == TaskStatus.Faulted)
output.WriteLine(" Task fault occurred");
else
{
output.WriteLine("test sent {0}",
tasks[ctr].Result.element);
Assert.True(true);
}
}
}
await Task.FromResult(...)
没有隐式的并行处理(请参见此问题进行解释)。相反,它是同步运行的。如果您希望将长时间运行的同步方法转换为可以与另一个方法并行调用的方法,则应改用await Task.Run(() => LongRunningTask());
。 - nicholasTask.Run(...)
调用中运行阻塞操作通常会将长时间操作推送到线程池线程中。如果这是ASP.NET Core处理程序,则已经在线程池上,因此除了不必要的上下文切换外,这没有任何影响。此外,如果滥用此模式,可能会导致线程池饥饿。简而言之,不要这样做。 - nicholas