Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我想知道使用TaskCompletionSource是否是一个错误的选择_C#_.net_Task Parallel Library_Taskcompletionsource - Fatal编程技术网

C# 我想知道使用TaskCompletionSource是否是一个错误的选择

C# 我想知道使用TaskCompletionSource是否是一个错误的选择,c#,.net,task-parallel-library,taskcompletionsource,C#,.net,Task Parallel Library,Taskcompletionsource,我必须在这里补充一点,我不是Stackoverflow上的一个熟练提问者,因此我很高兴收到关于我的问题为什么不适合这里的反馈。 当包装非异步调用时,等待TaskCompletionSource是件坏事吗 以下是我的用例: 我有一个处理程序类,它在事件发生时调用函数Func回调。处理程序从我的应用程序外部调用,并通知我的UI。 有两种方法A和B用作回调。A调用异步HTTP客户机,B执行计算。在这两种情况下,wait调用都将解冻UI,然后更新属性 A: B: 公共异步任务B(){ var tcs=n

我必须在这里补充一点,我不是Stackoverflow上的一个熟练提问者,因此我很高兴收到关于我的问题为什么不适合这里的反馈。

当包装非异步调用时,等待TaskCompletionSource是件坏事吗

以下是我的用例:

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

A:

B:

公共异步任务B(){
var tcs=new TaskCompletionSource();
等待tcs.Task;//解冻用户界面
//…复制图像字节并更新UI(长时间运行非异步)
SetResult(true);//在调用方法中释放字节
}
我的问题是,使用TaskCompletionSource包装非异步调用是一种不好的做法吗

文件说明如下

如果要为现有异步操作或事件创建任务包装,请使用TaskCompletionSource

另一种可能是调用Task.Run(),但我感觉更糟。 不使用Async将导致冻结UI,这并不是我真正想要的,尽管它可能是最干净的解决方案

------->更新

正如其他人所说,Task.Run()在这里非常好

我应该注意到我的B:看起来不一样 B:

公共异步任务B(…){
var tcs=new TaskCompletionSource();
//…重复字节
SetResult(true);//在调用方法中释放字节
等待tcs.Task;//解冻用户界面
//…复制图像字节并更新UI(长时间运行非异步)
}
使用下面的Task.Run()查找更好的选项


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

如果没有某种多线程处理,就无法在后台执行CPU绑定的任务

此代码

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 Task.Run( () => {
    // ... copy image bytes and update UI (long running not async)
});

…这当然更容易理解,这就是
Task.Run()
的用意。

Task.Run有什么问题?它不是为运行CPU绑定的方法而设计的吗?您应该更改标题和问题的前半部分,以询问/解释您真正想要什么。TaskCompletionSource是一个工具,一个专门的工具。您想做什么,为什么不使用
await
任务。运行
?B中的代码如何从
await
tcs.SetResult
?它将卡在
await
await tcs.Task不会解冻任何东西<代码>等待
不会解冻,它等待已经异步的操作完成,而不会阻塞线程。如果该操作(本例中为tcs)从未完成,
await
将不会在
await-httpClient.GetStringAsync()
中返回,
GetStringAsync()
是一个异步操作,
await
将在不阻塞线程的情况下等待它,并在该线程完成时恢复执行。并不是
wait
使
GetStringAsync
成为一种异步方法。你是对的,我可以使用Task.Run()。可以调用Task.Run()。我应该写tcs.SetResult(true);在等待之前。
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)
}
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
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)
});