我想知道使用TaskCompletitionSource是否是一个错误的选择

问题描述 投票:0回答:1

我必须在这里补充一下,我不是Stackoverflow的实践提问者,因此,我很高兴收到有关为何我的问题可能不适合此处的反馈。

包装一个非异步调用时,等待TaskCompletitionSource不好吗?

这是我的用例:

我有一个处理程序类,该类在事件发生时调用函数Func<T, Task>回调。从我的应用程序外部调用该处理程序,并通知我的UI。有两种方法A和B用作回调。 A在这里调用异步HTTP客户端,B在这里进行计算。在这两种情况下,await调用都会解冻UI,然后更新属性。

A:

public async Task A(){
 result = await CallHttpClient(...) // unfreeze UI
 // ... copy image bytes and update UI (long running not async)
 // release bytes in calling method
}

B:

public async Task B(){
 var  tcs = new TaskCompletionSource<bool>();
 await tcs.Task; // unfreeze UI
 // ... copy image bytes and update UI (long running not async)
 tcs.SetResult(true); // release bytes in calling method
}

我的问题在这里,使用TaskCompletionSource封装非异步调用是否是一种不好的做法?

该文档规定以下内容。

如果要为现有的异步操作或事件创建任务包装,请使用TaskCompletionSource。 https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming

另一种可能性是调用Task.Run(),但对我来说感觉更糟。不使用Async会导致UI冻结,虽然这可能是最干净的解决方案,但这并不是我真正想要的UI。

------->更新

作为其他人的状态,Task.Run()在这里非常好。

我应该注意我的B:看起来与众不同B:

public async Task B(...){
 var  tcs = new TaskCompletionSource<bool>();
 // ... duplicate bytes
 tcs.SetResult(true); // release bytes in calling method
 await tcs.Task; // unfreeze UI
 // ... copy image bytes and update UI (long running not async)
}

通过下面的Task.Run()查找更好的选项。

我还应注意,当方法离开字节时(示例中未显示)被释放。

c# .net task-parallel-library taskcompletionsource
1个回答
1
投票
此代码...

var tcs = new TaskCompletionSource<bool>(); await tcs.Task; // unfreeze UI // ... copy image bytes and update UI (long running not async) tcs.SetResult(true); // release bytes in calling method

...将阻塞await,因为直到之后才调用SetResult,从而导致某种死锁。

我想你可以像这样做些疯狂的事情

var tcs = new TaskCompletionSource<bool>(); Parallel.Invoke ( () => await tcs.Task, () => { // ... copy image bytes and update UI (long running not async) tcs.SetResult(true); // release bytes in calling method } );

但是我不确定这是否也可以。执行此操作的标准方法是

await Task.Run( () => {
    // ... copy image bytes and update UI (long running not async)
});

...这当然更容易理解,并且它的含义是Task.Run()

© www.soinside.com 2019 - 2024. All rights reserved.