Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.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#_.net_Asynchronous_Async Await - Fatal编程技术网

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
,而不是相反。