繁体   English   中英

将TaskCompletionSource转换为Task.FromResult <TResult> ?

[英]Convert TaskCompletionSource to Task.FromResult<TResult>?

我有这个简单的代码,它以异步方式启动一个方法。 它使用TCS以使用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

暂无
暂无

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

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