【发布时间】:2018-06-13 15:44:09
【问题描述】:
我对 async/await 还很陌生,我在处理表单关闭前未完成的任务时遇到了困难。它在大多数情况下都可以正常工作,但有时我需要检索数据集或修改表,并且查询太慢而无法在 UI 线程关闭之前完成。
我可以使用 Task.Wait(),或者使用 ExecuteNonQuery() 而不是 ExecuteNonQueryAsync(),但我想在表单关闭之前避免死锁。我已经搜索了其他一些帖子,但我仍然对最好的方法有点不确定。
以下示例是在关闭表单之前更新支持呼叫的状态。
private async void frmSupportDetails_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
// Sets call to incomplete if it was pending/transferred
if (status != "Complete" && status != "Incomplete")
{
dbQuery = "UPDATE SupportCalls SET [Status] = @status, [CompletedNote] = @completedNote WHERE CallNum = @callNum";
await sql.executeAsync(dbQuery, new OleDbParameter("@status", "Incomplete"), new OleDbParameter("@completedNote", txtCompletedNote.Text), new OleDbParameter("@callNum", ProgOps.selectedCallNum));
}
// Asks to log callback date
if (promptCallBack == true)
{
DialogResult callbackOption = MessageBox.Show("Would you like to log that you are returning the customer's call?", "Callback Date", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (callbackOption == DialogResult.Yes)
{
dbQuery = "UPDATE SupportCalls SET CallbackDate = Now() WHERE CallNum = @callNum";
await sql.executeAsync(dbQuery, new OleDbParameter("@callNum", ProgOps.selectedCallNum));
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Occurred - frmClose()", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
}
public async Task executeAsync(string dbQuery, params OleDbParameter[] parameters)
{
using (var dbConn = new OleDbConnection(CONNECT_STRING))
using (var dbComm = new OleDbCommand(dbQuery, dbConn))
{
if (parameters != null)
dbComm.Parameters.AddRange(parameters);
await dbConn.OpenAsync().ConfigureAwait(false);
await dbComm.ExecuteNonQueryAsync().ConfigureAwait(false);
}
}
【问题讨论】:
-
这不应该是异步的,因为你没有那样使用它。话虽如此,您为什么担心表单关闭时出现死锁?
-
@RyanJohnson 您可能想阅读我发现的这篇 StackOverflow 帖子,它提供了一个示例,说明如果您一心想要对 FormClosing 事件使用异步,该怎么办,(stackoverflow.com/questions/16656523/…)
-
@RyanWilson 使函数异步不会使其在另一个线程上运行。它只是意味着它在被调用后立即返回。使函数异步的许多可能方法之一是让它在另一个线程中工作,但这绝不是使函数异步的唯一方法。这个特定的示例不是在另一个线程中工作,而是在与数据库进行 IO。
-
@Trey frmSupportDetails 是一个子表单,如果非异步查询遇到任何网络问题,我过去曾遇到过 UI 变得无响应并导致整个程序崩溃的问题。跨度>
-
@Servy 如果它立即返回,那么在方法内部完成的工作是什么?我只是问,因为我一直在尝试阅读 async 并理解它。我认为异步的目的是释放 UI 线程以保持 UI 响应。
标签: c# winforms asynchronous async-await