gpt4 book ai didi

c# - 使用 Async 和 Await 中断数据库调用(使用 Dapper)

转载 作者:可可西里 更新时间:2023-11-01 09:06:17 28 4
gpt4 key购买 nike

我们从 Dapper 请求返回数千个对象并达到参数限制 (2100),因此决定分块加载它们。

我认为这是尝试 Async Await 的好机会 - 这是我第一次尝试,所以可能会犯小学生错误!

断点被击中,但整个事情就是没有返回。它没有抛出错误 - 一切似乎都在黑洞中进行!

请帮忙!

这是我原来的方法——它现在调用异步方法

    public List<MyObject> Get(IEnumerable<int> ids)
{
return this.GetMyObjectsAsync(ids).Result.ToList();
} //Breakpoint on this final bracket never gets hit

我添加了这个方法来将 id 分成 1000 个 block ,然后等待任务完成

    private async Task<List<MyObject>> GetMyObjectsAsync(IEnumerable<int> ids)
{
var subSets = this.Partition(ids, 1000);

var tasks = subSets.Select(set => GetMyObjectsTask(set.ToArray()));

//breakpoint on the line below gets hit ...
var multiLists = await Task.WhenAll(tasks);

//breakpoint on line below never gets hit ...
var list = new List<MyObject>();
foreach (var myobj in multiLists)
{
list.AddRange(myobj);
}
return list;
}

下面是任务...

    private async Task<IEnumerable<MyObject>> GetMyObjectsTask(params int[] ids)
{
using (var db = new SqlConnection(this.connectionString))
{
//breakpoint on the line below gets hit
await db.OpenAsync();
return await db.QueryAsync<MyObject>(@"SELECT Something FROM Somewhere WHERE ID IN @Ids",
new { ids});
}
}

以下方法只是将 id 列表分成 block - 这似乎工作正常......

    private IEnumerable<IEnumerable<T>> Partition<T>(IEnumerable<T> source, int size)
{
var partition = new List<T>(size);
var counter = 0;

using (var enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
partition.Add(enumerator.Current);
counter++;
if (counter % size == 0)
{
yield return partition.ToList();
partition.Clear();
counter = 0;
}
}

if (counter != 0)
yield return partition;
}
}

最佳答案

您正在以使用 async/await 的方式制造死锁情况结合 Task<T>.Result .

违规行是:

return this.GetMyObjectsAsync(ids).Result.ToList();

GetMyObjectsAsync(ids).Result阻塞当前同步上下文。但是GetMyObjectsAsync使用 await它为当前同步上下文安排一个延续点。我相信您可以看到这种方法的问题:永远无法执行延续,因为当前同步上下文被 Task.Result 阻止了。 .

在某些情况下可行的一种解决方案是使用 ConfigureAwait(false)这意味着延续可以在任何同步上下文中运行。

但总的来说,我认为最好避免 Task.Resultasync/await .


请注意,这种死锁情况是否实际发生取决于调用异步方法时使用的同步上下文。对于 ASP.net、Windows 窗体和 WPF,这将导致死锁,但据我所知,它不会用于控制台应用程序。 (感谢 Marc Gravell 的评论)


Microsoft 有一篇关于 Best Practices in Asynchronous Programming 的好文章. (感谢 ken2k)

关于c# - 使用 Async 和 Await 中断数据库调用(使用 Dapper),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24572908/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com