在async / await上阻塞主线程

时间:2016-06-16 03:18:04

标签: c# .net asynchronous async-await dapper

我试图使我的基础存储库类异步,我遇到了一些麻烦。我在我的C#应用​​程序中使用Dapper ORM。

基本方法

for(Rect rect : faces.toArray()){
    Imgproc.rectangle(frame, rect.tl(), rect.br(), new Scalar(0,0,255),3);
    Rect rectCrop = new Rect(rect.x, rect.y , rect.width, rect.height);
    Mat imageROI = grayFrame.submat(rectCrop);

    //frame is the original mat with the correct size
    Imgproc.GaussianBlur(imageROI, frame, new Size(55, 55), 55);
}

通话方法

INSERT INTO temp (input, str, userId)
VALUES (9, 7, 'sure.');

一切都是为了我。我有使用async关键字修饰的方法声明。我在等待异步方法。

我遇到的问题是protected async Task<List<T>> Read<T>(CommandDefinition cmd) { using(SqlConnection myCon = new SqlConnection(Config.DBConnection)) { await myCon.OpenAsync(); IEnumerable<T> results = await myCon.QueryAsync<T>(cmd); List<T> retVal = results.ToList(); myCon.Close(); return retVal; } } 上的线程阻塞了。这是我第一次尝试使用async和await,所以我确信我做错了什么,但这并不明显。请帮忙!

2 个答案:

答案 0 :(得分:4)

发布的阅读代码很好。问题出在消费代码中。如果您在通话中回复asyncWait()或其前一个Result,请TaskTask发生死锁,这很常见链

在这些情况下,一般建议适用:don't block on async code。开始使用async/await后,您应该在整个调用链中使用async/await

因此,您的调用方法变为

public Task<List<Category>> GetAllActiveCategoriesAsync(Guid siteGuid) {
    return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid);
}

......或

public async Task<List<Category>> GetAllActiveCategoriesAsync(Guid siteGuid) {
    List<Category> result = await base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid);

    // Do something.

    return result;
}

答案 1 :(得分:1)

罪魁祸首是:

return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid).Result;

正如Kirill所指出的,只要您在任务中使用.Wait().Result,就会同步阻止。你需要做的是:

public Task<List<Category>> GetAllActiveCategories(Guid siteGuid) {
    return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid);
}

这会将一个Task返回给 this 方法的调用方法,依此类推......它必须是异步的&#34;一直向上&#34;。

如果此代码的顶级使用者是ASP.NET,那么你很好。只需返回Task<IActionResult>(或任务中包含的相应返回类型),框架将为您排序await

如果你正在编写一个控制台应用程序,或者无法使其完全异步,那么你必须阻止.Result或者制作方法async void并使用await。遗憾的是,这两个都不是一个很好的解决方案。 Async / await非常具有攻击性,因为你真的必须在整个堆栈中使用它。