我在将EntityFrmework 6.2异步方法应用于winform应用程序时遇到了问题。 我们使用自定义类来管理基于单个活动设置的同步或异步EntityFrmework访问。当我们使用同步访问时,一切正常。当使用异步调用时,我们会遇到此问题:在先前的异步操作完成之前,第二个操作是在此上下文上启动的。使用“ await”来确保在此上下文上调用另一个方法之前,所有异步操作都已完成。不保证任何实例成员都是线程安全的。 我们已经阅读了很多有关此问题的文章,但没有一个可以帮助我们解决问题。
我们知道问题与从同步之一调用异步方法有关,不幸的是,我们无法将调用方法从同步转换为异步。 我们从项目中提取了两种方法,以证明所描述的行为
public void AddLoadingRequest(Func<Task> fnAsync, Action fnSync, Action bsa)
{
try
{
Task task = Task.Run(async () => await DoDataSource(fnAsync, fnSync, bsa));
_lstTask.Add(task);
if (task.IsFaulted)
throw task.Exception;
}
catch (Exception ex)
{
MessageBox.Show($"Error {ex.Message}");
}
}
protected async Task DoDataSource(Func<Task> fnAsync, Action fnSync, Action bsa)
{
try
{
if (_bLoadingFKTableAsync == true)
await fnAsync();
else
fnSync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Loading Error");
throw;
}
}
调用方法:
private void btnTest_Click(object sender, EventArgs e)
{
NWContext wContext = new NWContext();
Customers cust = wContext.Customers.FirstOrDefault(w => w.CustomerID == "RATTC");
BindingSource bsCustomer = new BindingSource();
BindingSource bsOrders = new BindingSource();
BindingSource bsCustomerDemographics = new BindingSource();
bsCustomer.DataSource = cust;
_bLoadingFKTableAsync = true;
AddLoadingRequest(
() => wContext.Entry(cust).Collection(typeof(Orders).Name).LoadAsync(),
() => wContext.Entry(cust).Collection(typeof(Orders).Name).Load(),
() =>
{
bsOrders.SuspendBinding();
bsOrders.DataSource = cust.Orders;
bsOrders.ResumeBinding();
});
AddLoadingRequest(
() => wContext.Entry(cust).Collection(typeof(CustomerDemographics).Name).LoadAsync(),
() => wContext.Entry(cust).Collection(typeof(CustomerDemographics).Name).Load(),
() =>
{
bsCustomerDemographics.SuspendBinding();
bsCustomerDemographics.DataSource = cust.CustomerDemographics;
bsCustomerDemographics.ResumeBinding();
});
}
我们期望EntityFramework在异步模式下加载对象的两个子级集合,同时出现错误:在先前的异步操作完成之前,第二个操作在此上下文上启动。使用“ await”来确保在此上下文上调用另一个方法之前,所有异步操作都已完成。不保证任何实例成员都是线程安全的。
答案 0 :(得分:0)
问题是:我们如何从现有同步方法内部调用两个或多个异步EF请求?
您需要两个或多个数据库上下文。每个人一次只能发送一个请求。
另一方面,我强烈建议您将方法更改为async
。像这样跳过await
是一种“失火”的方法,它有两个主要问题: