我有以下异步方法,该方法删除记录并将其插入MySQL数据库
public async Task<Res> myNewFunc(int id, IEnumerable<Sample> obs)
{
using (var t = DbConnection.GetTransaction())
{
await DbConnection.DeleteMany<M1>().Where(x.Id == id).ExecuteAsync();
foreach (var ob in obs)
{
await DbConnection.InsertAsync(ob);
}
t.Complete();
}
}
调用myNewFunc()的方法:
public async Task<T> method()
{
//...
//...
var response = await DAL.myNewFunc(id, obs);
}
异步方法使用 foreach 循环进行访问。
foreach(var num in nums)
{
method();
}
我使用上述代码的MySQL面临死锁问题。
因为你没有在最后一个 for 循环中等待,所以它将为所有这些线程启动线程,并同时并行运行所有这些线程。 如果你在这里有很多数据,他们都会为相同的资源而战。 您最终会在每种情况下创建事务,然后从表中删除多个记录。 然而,这可能不是真正的根本问题。 在所有 ExecuteAsync 调用中,您都不执行 .ConfigureAwait(false). 这意味着在运行每个语句后,它会等待,直到它可以在原始线程(在本例中为 UI 线程)上恢复其工作。 我不知道你在 for 循环之后做了什么,但这个线程可能永远不会放手,所以这些数据库调用都无法返回并且你得到死锁。
您可以尝试解决此问题的两种方法:
-
每个 Async() 调用都需要是 Async()。ConfigureAwait(false). 如果确实是 UI 线程被锁定,这可能会修复它。
-
在最后一个 for 循环中,您需要等待每个循环,因为数据库资源可能都被占用了。 请改用以下代码:
foreach(var num in nums)
{
method().GetAwaiter().GetResult();
}
这一次只能处理一个。 对于#2,您可能还需要执行#1。