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());
}
}
在调用类中等待这个方法,其中 - 在一段时间之后 - 我想在不明确阻塞的情况下使用结果。
我可以通过在调用代码中返回ContinueWith
和Task<IEnumerable<Foo>>
来解决此问题,以便不使用上面的FirstOrDefault()
。
从我所看到的上面的阻塞是臭的,更糟糕的是会导致问题,可能是一个僵局。我对么?
答案 0 :(得分:5)
在已完成的Result
上调用Task
(知道,如果其继续触发,任务将完成)不会导致死锁。
当任务需要能够在另一个线程/上下文上调度操作以便能够完成时,会导致死锁,但该线程/上下文在结果上阻塞。由于任务已经完成,阻塞线程/上下文不可能阻止它完成。
也就是说,您可以轻松地await
完成任务,而不是致电ContinueWith
。
答案 1 :(得分:1)
正如@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
做出意外和愚蠢的事情,否则这不会导致死锁。这不会是问题中代码的问题。