我正在开发一个与Access DB通信的c#应用程序。
目前,我正在使用c#5的async / await功能将db调用转换为异步调用。 在将数据库访问函数转换为异步对应项(即DbConnection.Open - > DbConnection.OpenAsync,DbDataReader.ExecuteReader - > DbDataReader.ExecuteReaderAsync ...)并插入await / async后,我最终得到了这样的方法: / p>
public async Task<Dictionary<int, ProductStockData>> getStockAmountPerOrderIntervalAsync() {
var orderedProductsAndQuantities = await getOrderedProductsAndQuantitiesAsync().ConfigureAwait(false);
string stockAmountPerOrderIntervalQuery = @"SELECT {...}";
using (OleDbConnection dbConnection = new OleDbConnection(ConnectionString)) {
await dbConnection.OpenAsync().ConfigureAwait(false);
using (OleDbCommand cmd = new OleDbCommand(stockAmountPerOrderIntervalQuery, dbConnection)) {
DbDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false);
{...}
return productsAndStockAmountsPerInterval;
}
}
}
调试时我发现两个异步调用总是在现场执行(而不是异步),阻塞调用线程(以及WPF应用程序)。
这个方法是从一系列方法中调用的,所有方法都用async修饰符标记并调用下一个方法,如下所示:
await [method]().ConfigureAwait(false);
在这个链的开头是来自ui线程的事件处理程序调用,如下所示:
async void mDbManager_OnConnectionEstablished() {
await updateStockData(); // starting the chain of await call leading up to the aforementioned method call
updateMissingProductsString();
}
在发现代码本身没有问题后,我开始研究数据库连接。 我正在使用Access数据库文件(.mdb),我当前的连接字符串是:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source="{...}"
我也试过这个:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source="{...}"
我做了一些研究,但我唯一能找到的是,在.Net 4.5之前你必须附加&#34; Asynchronous Processing = true&#34;到连接字符串以允许异步调用。但我正在使用.Net 4.5.1。即使我追加它,它也无法正常工作。
有人知道我是否还需要做其他事情才能启用对Access DB的异步调用?
编辑: 我也尝试使用带有此连接字符串的OdbcConnection:
Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq={...}
对异步数据库调用具有相同的阻止效果...
答案 0 :(得分:0)
我认为您必须删除ConfigureAwait(false)调用才能使解决方案异步。否则,将不会进行编组,并且您的UI线程将被阻止。
一些偏离主题的建议:
我还建议迁移到Entity Framework,它现在有一些很好的异步支持。只有当我必须完全控制数据访问或利用某些尚未支持的功能(即Oracle UDT)时,我才会直接使用ADO .NET
希望这会有所帮助。
答案 1 :(得分:0)
如果您只需要取消阻止UI线程,则可以将阻止调用强制执行到这样的新任务上:
private async void MyButton_Click(object sender, EventArgs e)
{
await Task.Run(() => getStockAmountPerOrderIntervalAsync());
}
这使您可以保留其余代码。
来源: https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html