以下启用异步的代码是否容易导致死锁
Is the following async enabled code liable to cause a deadlock
public async Task<Foo> Execute(int id)
{
var parameters = new { id};
using (var con = new SqlConnection(this.connectionString))
{
await con.OpenAsync();
return await con.QueryAsync<foo>(
"dbo.uspGetMeFoo",
parameters,
commandType: CommandType.StoredProcedure,
commandTimeout: int.Parse(ConfigurationManager.AppSettings["SqlCommandTimeout"]))
.ContinueWith(task => task.Result.FirstOrDefault());
}
}
此方法在调用 class 中等待,其中 - 一段时间后 - 我想在不显式阻塞的情况下使用结果。
我可以通过在调用代码中返回 Task<IEnumerable<Foo>>
和 FirstOrDefault()
来解决这个问题,不使用上面的 ContinueWith
。
据我所知,上面的阻塞很臭,更糟的是会导致问题,可能是死锁。我对么?
在已经完成的 Task
上调用 Result
(您 知道 如果继续触发任务将会完成)不会导致僵局。
当任务需要能够在另一个 thread/context 上安排操作以便能够完成,但 thread/context 阻塞了结果时,就会导致死锁。由于任务已经完成,阻止 thread/context 不可能阻止它完成。
也就是说,您可以轻松 await
任务而不是调用 ContinueWith
。
正如@Servy所说,你可以很容易地写
public async Task<Foo> Execute(Foo foo )
{
var parameters = new { id = id};
using (var con = new SqlConnection(this.connectionString))
{
var timeout = int.Parse(
ConfigurationManager.AppSettings["SqlCommandTimeout"]);
await con.OpenAsync();
var query = await con.QueryAsync<Foo>(
"dbo.uspGetMeFoo",
parameters,
commandType: CommandType.StoredProcedure,
commandTimeout: timeout);
return query.FirstOrDefault();
}
}
这不会导致死锁,除非 dbo.uspGetMeFoo
做了一些意想不到的蠢事。这不是问题中代码的问题。
public async Task<Foo> Execute(int id)
{
var parameters = new { id};
using (var con = new SqlConnection(this.connectionString))
{
await con.OpenAsync();
return await con.QueryAsync<foo>(
"dbo.uspGetMeFoo",
parameters,
commandType: CommandType.StoredProcedure,
commandTimeout: int.Parse(ConfigurationManager.AppSettings["SqlCommandTimeout"]))
.ContinueWith(task => task.Result.FirstOrDefault());
}
}
此方法在调用 class 中等待,其中 - 一段时间后 - 我想在不显式阻塞的情况下使用结果。
我可以通过在调用代码中返回 Task<IEnumerable<Foo>>
和 FirstOrDefault()
来解决这个问题,不使用上面的 ContinueWith
。
据我所知,上面的阻塞很臭,更糟的是会导致问题,可能是死锁。我对么?
在已经完成的 Task
上调用 Result
(您 知道 如果继续触发任务将会完成)不会导致僵局。
当任务需要能够在另一个 thread/context 上安排操作以便能够完成,但 thread/context 阻塞了结果时,就会导致死锁。由于任务已经完成,阻止 thread/context 不可能阻止它完成。
也就是说,您可以轻松 await
任务而不是调用 ContinueWith
。
正如@Servy所说,你可以很容易地写
public async Task<Foo> Execute(Foo foo )
{
var parameters = new { id = id};
using (var con = new SqlConnection(this.connectionString))
{
var timeout = int.Parse(
ConfigurationManager.AppSettings["SqlCommandTimeout"]);
await con.OpenAsync();
var query = await con.QueryAsync<Foo>(
"dbo.uspGetMeFoo",
parameters,
commandType: CommandType.StoredProcedure,
commandTimeout: timeout);
return query.FirstOrDefault();
}
}
这不会导致死锁,除非 dbo.uspGetMeFoo
做了一些意想不到的蠢事。这不是问题中代码的问题。