Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.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# 如果先提取任务,则异步任务会死锁_C#_Async Await_Task_Task Parallel Library_Deadlock - Fatal编程技术网

C# 如果先提取任务,则异步任务会死锁

C# 如果先提取任务,则异步任务会死锁,c#,async-await,task,task-parallel-library,deadlock,C#,Async Await,Task,Task Parallel Library,Deadlock,我正在使用Microsoft的asynchHelper()从同步上下文调用异步方法。这很好: Result r = AsyncHelper.RunSync(async () => await SomeClass.SomeMethodAsync()); 但是,如果我提取任务,然后尝试同步运行此提取的任务,则会遇到死锁: Task<Result> t = SomeClass.SomeMethodAsync(); Result r = AsyncHelper.RunSync(asy

我正在使用Microsoft的
asynchHelper
()从同步上下文调用异步方法。这很好:

Result r = AsyncHelper.RunSync(async () => await SomeClass.SomeMethodAsync());
但是,如果我提取任务,然后尝试同步运行此提取的任务,则会遇到死锁:

Task<Result> t = SomeClass.SomeMethodAsync();
Result r = AsyncHelper.RunSync(async () => await t);
Task t=SomeClass.SomeMethodAsync();
结果r=asynchHelper.RunSync(async()=>wait t);

为什么会发生这种情况,以及可以做些什么来运行此操作?

AsyncHelper。RunSync
使用确保在没有上下文的情况下调用其委托,从而使其可以安全地阻止(假设在线程池线程上调用委托是安全的)。在代码中,
SomeMethodAsync
在线程池线程上执行,因此任何
wait
s都不会执行

我们可以做些什么来实现这一目标

那么,您将使用第一个代码示例,而不是第二个

如果您希望有一个表示要运行的某些代码的构造,那么应该使用委托类型,例如
Func
。例如:

Func<Task<Result>> func = () => SomeClass.SomeMethodAsync();
Result r = AsyncHelper.RunSync(func);
Func-Func=()=>SomeClass.SomeMethodAsync();
结果r=asynchHelper.RunSync(func);

对于异步代码,
任务
不代表要运行的某些代码;它表示一些已经启动的代码。使用
Func
表示要运行的某些代码。

asynchHelper。RunSync
使用确保在没有上下文的情况下调用其委托,从而使其可以安全地阻止(假设在线程池线程上调用委托是安全的)。在代码中,
SomeMethodAsync
在线程池线程上执行,因此任何
wait
s都不会执行

我们可以做些什么来实现这一目标

那么,您将使用第一个代码示例,而不是第二个

如果您希望有一个表示要运行的某些代码的构造,那么应该使用委托类型,例如
Func
。例如:

Func<Task<Result>> func = () => SomeClass.SomeMethodAsync();
Result r = AsyncHelper.RunSync(func);
Func-Func=()=>SomeClass.SomeMethodAsync();
结果r=asynchHelper.RunSync(func);

对于异步代码,
任务
不代表要运行的某些代码;它表示一些已经启动的代码。使用
Func
表示要运行的一些代码。

通过调用
\u myTaskFactory.StartNew
注意
asynchHelper.RunSync
是如何运行
SomeClass.SomeMethodAsync
。这确保开始执行
SomeClass.SomeMethodAsync
的线程上没有安装SynchronizationContext。实际上,
asynchHelper.RunSync
之所以有效,是因为它在没有安装
SynchronizationContext
的线程上调用
SomeMethodAsync
。避免这种情况的方法是确保在没有同步上下文的线程上调用
SomeMethodAsync
,方法是使用类似于
asynchHelper.RunAsync
…这看起来很像“syncoverasync”,在这种情况下是的:这是一个众所周知的问题,这正是您不打算这么做的原因“异步同步”。最终,你不能稍微异步;你需要一直异步。那么,这个问题唯一支持的答案就是删除异步同步:
Result r=wait SomeClass.SomeMethodAsync();
(并使你正在处理的代码路径基于
async
/
[ValueTask][/code>)通过调用
\u myTaskFactory.StartNew
,注意
AsyncHelper.RunSync
如何运行
SomeClass.SomeMethodAsync
。这确保开始执行
SomeClass.SomeMethodAsync
的线程上没有安装SynchronizationContext。实际上,
AsyncHelper.RunSync
可以工作,因为它调用
SomeMethodAsync
在没有安装
SynchronizationContext
的线程上。避免这种情况的方法是确保在没有
SynchronizationContext
的线程上调用
SomeMethodAsync
,方法是使用类似于
AsynchHelper.RunAsync
…这看起来很像“异步同步”,在这种情况下是的:这是一个众所周知的问题,这正是为什么您不打算执行“异步同步”的原因。最终,你不能去稍微异步;你需要一路异步。那么,这个问题唯一受支持的答案就是删除异步同步:
Result r=wait SomeClass.SomeMethodAsync()(并使您正在处理的代码路径异步
/
[ValueTask][]
-based)