简体   繁体   English

使用Result时出现死锁

[英]Deadlock when using Result

I have read that I should only use Result instead of await when I am absolutely sure that an operation is completed. 我已经读过,当我完全确定操作完成时,我应该只使用Result而不是await I am not really sure what happens underneath and would like to ask experienced programmers if this is a perfectly safe usage of await / Result / async . 我不确定下面发生了什么,并且想问一下有经验的程序员,如果这是一个非常安全的await / 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);
    }
}

This is not safe. 这不安全。 The operation hasn't completed yet when you use Task.Result 使用Task.Result时,操作尚未完成

When you call an async method it runs synchronously until it reaches an await and then returns to the caller with a task that represents the asynchronous operation. 当您调用异步方法时,它会同步运行,直到达到await,然后返回带有表示异步操作的任务的调用方。

The task isn't completed and using Task.Result will block the calling thread. 任务未完成,使用Task.Result将阻止调用线程。

You should await the returned task instead, or use the synchronous option. 您应该等待返回的任务,或使用同步选项。

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);
    }
}

It is safe, though it ends up blocking until the Execute is complete. 它是安全的,但它会在Execute完成之前结束阻塞。 Accessing Task.Result is equivalent to: 访问Task.Result相当于:

 Task<int> task = Execute("...");
 task.Wait(); // blocks until done
 return 0 < task.Result;

If you wanted to further the await chain, you could have Success return a Task<bool> instead. 如果你想进一步改进await链,你可以让Success返回一个Task<bool>

Note that there is a potential for a deadlock depending on the current SynchronizationContext . 请注意,根据当前的SynchronizationContext可能存在死锁。 If your SynchronizationContext is single-threaded, then your call to Task.Result ends up blocking and waiting for Execute to finish, but Execute is waiting for you to release the thread so it can continue. 如果您的SynchronizationContext是单线程的,那么您对Task.Result的调用Task.Result会阻塞并等待Execute完成,但Execute正在等待您释放该线程以便它可以继续。 If you're in a GUI app (using a single-threaded SynchronizationContext by default) or ASP.NET, then you'd want to consider adding ConfigureAwait(false) to have Execute run on a thread pool thread instead. 如果您使用的是GUI应用程序(默认情况下使用单线程SynchronizationContext)或ASP.NET,那么您需要考虑添加ConfigureAwait(false)以使Execute在线程池线程上运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM