将TaskCompletionSource转换为Task.FromResult<;TResult>;
本文关键字:lt TResult gt FromResult TaskCompletionSource 转换 Task | 更新日期: 2023-09-27 18:20:02
我有这个简单的代码,它异步启动一个方法。它使用CCD_ 1来用Task包装代码。
Task<int> DoWork()
{
var source = new TaskCompletionSource <int>();
Thread.Sleep(220);
source.SetResult(9999999);
return source.Task;
}
void Main()
{
Console.WriteLine(1);
var t1=Task.Factory.StartNew(()=>DoWork());
t1.ContinueWith(_=>Console.WriteLine ("doing something different "));
t1.ContinueWith(_=>Console.WriteLine ("finished , value is ="+_.Result.Result));
Console.WriteLine(2);
Console.ReadLine();
}
输出:
1
2
doing somethign different //those last 2 lines can be swapped
finished , value is =9999999
但现在,我想将其转换为使用Task.FromResult<TResult>
。
这是一个很差的文档,所以我想知道,我如何才能将上面的代码转换为使用Task.FroResult
?
使用FromResult
最简单的方法是:
public Task<int> DoWork()
{
return Task.FromResult(99999);
}
但它在功能上完全等同于做:
var tcs = new TaskCompletionSource<int>();
tcs.SetResult(99999);
return tcs.Task;
因此它在220毫秒内不会休眠。对于"延迟"变体,最简单的方法是:
public async Task<int> DoWork()
{
await Task.Delay(220);
return 99999;
}
这个版本的行为与您提供的示例非常接近。
在您的代码中,只有在同步等待结束后才返回Task
,因此您的代码等效于:
Task<int> DoWork()
{
Thread.Sleep(220);
return Task.FromResult(9999999);
}
但如果您立即返回Task
,然后阻止其他线程:
Task<int> DoWork()
{
var source = new TaskCompletionSource<int>();
Task.Run(() =>
{
Thread.Sleep(220);
source.SetResult(9999999);
});
return source.Task;
}
(注意:我并不是说你应该在真实的代码中这样做。)
Task.FromResult()
无法模拟此代码,因为它总是创建一个已经完成的Task
。