C# 使用结果时出现死锁
我已经读到,我应该只使用C# 使用结果时出现死锁,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,我已经读到,我应该只使用结果,而不是等待,当我绝对确定某项操作已完成时。我真的不知道下面会发生什么,我想问问有经验的程序员,这是否是使用wait/Result/async的完全安全的方法 public static bool Success() { return 0 < Execute("DELETE FROM Table WHERE Id = 12").Result; } public static async Task<int> Execute(string sq
结果
,而不是等待
,当我绝对确定某项操作已完成时。我真的不知道下面会发生什么,我想问问有经验的程序员,这是否是使用wait
/Result
/async
的完全安全的方法
public static bool Success()
{
return 0 < Execute("DELETE FROM Table WHERE Id = 12").Result;
}
public static async Task<int> Execute(string sql)
{
using (var con = Connection)
{
con.Open();
return await con.ExecuteAsync(sql);
}
}
公共静态bool Success()
{
返回0
这不安全。使用任务时操作尚未完成。结果
当您调用一个异步方法时,它会同步运行,直到到达等待,然后返回给调用方一个表示异步操作的任务
任务未完成,使用task.Result
将阻止调用线程
您应该等待返回的任务,或者使用同步选项
public static Task<bool> SuccessAsync()
{
return 0 < await ExecuteAsync("DELETE FROM Table WHERE Id = 12");
}
public static async Task<int> ExecuteAsync(string sql)
{
using (var con = Connection)
{
con.Open();
return await con.ExecuteAsync(sql);
}
}
公共静态任务成功同步()
{
返回0
它是安全的,尽管它最终会阻塞,直到执行完成。访问任务。结果相当于:
Task<int> task = Execute("...");
task.Wait(); // blocks until done
return 0 < task.Result;
Task Task=Execute(“…”);
task.Wait();//完成前阻止
返回0
如果您想进一步执行wait
链,您可以选择Success
返回任务
请注意,根据当前的SynchronizationContext
,可能会出现死锁。如果您的SynchronizationContext
是单线程的,那么您对Task.Result
的调用将阻塞并等待Execute
完成,但是Execute
正在等待您释放线程,以便它可以继续。如果您在GUI应用程序中(默认情况下使用单线程同步上下文)或ASP.NET,那么您需要考虑添加<代码> ConfigureAwait(false)以在线程池线程上运行<代码>执行<代码>。@ i3ARNONE,因为没有未定义的行为或异常,我将其归类为“安全”。阻塞不是不安全的,它只是它的方式-有时你想要它,有时你不想要。这绝对不是“安全的”。从UI线程使用.Result
可能会死锁。因此,有一半的async wait
问题是因为人们不理解当您阻止一个异步方法时会发生什么。无法访问。跨线程的结果(不仅仅是UI)也可能出现死锁?@JohnathonSullinger当您在线程上阻塞SyncronisationContext
将用于执行完成时,死锁就会发生。在“stock.NET”文件中,UI同步上下文(一个用于Winforms,一个用于WPF)是唯一的单线程同步上下文。“默认上下文”使用线程池,因此除非您阻止线程池中的每个线程,否则您不会死锁。@ScottChamberlain它使用线程池中的线程,但它有自己的SynchronizationContext,这里的死锁不是因为单个线程,而是因为单个请求上下文。在无法等待的情况下,您应该对任务执行.Wait()
,或者让任务执行它的任务,并添加您想要在正在运行的任务上继续运行的任何其他代码。你不能总是等待,有些时候这不是一个好时机option@JohnathonSullinger做.Wait()
和做.Result
一样糟糕。在不能等待的情况下,不应该在调用堆栈中的任何位置使用async/await。您应该改为执行同步调用。@JohnathonSullinger肯定会的。async void
等同于启动异步操作,并且从不对其调用wait
。至于死锁,请参见“图3异步代码阻塞时常见的死锁问题”@JohnathonSullinger,它们都是线程安全的。那不是重点。死锁的发生是因为您正在同步等待只能使用同一线程完成的任务(即阻塞线程)。因此线程等待自己。无论您是使用等待
还是使用结果
等待
可能重复的我已经读到,当我绝对确定操作已完成时,我应该只使用结果而不是等待。
您在哪里读到的?这是完全错误的。@StephenCleary好吧。。。这是你的答案@伦道夫:嗯,整个答案是关于为什么你应该使用wait
而不是Result
,而不是相反。