如何处理来自非 UI 线程的异步 SQL 查询
所有,我已经成功地使用 ADO.NET 来利用类似于下面的示例的异步 SQL 查询。在所示示例中,方法 ExecNonQuery 是从 UI 线程调用的。这很好用,但我想知道如果我从非 UI 线程调用 ExecNonQuery 我将如何处理回调?
笔记。显然,在这种情况下,我会修改 ExecNonQuery,以便相应地处理或删除诸如 this.toolStripStatusLabel1.Text
之类的内容。
public bool ExecNonQuery(string strCmd, string strUserMsg = "")
{
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = strCmd;
cmd.CommandTimeout = 0;
bIsExecuting = true;
AsyncCallback callback = new AsyncCallback(HandleCallback);
cmd.BeginExecuteNonQuery(callback, cmd);
return true;
}
catch (Exception Ex)
{
bIsExecuting = false;
this.toolStripStatusLabel1.Text = String.Format("Ready (last error: {0})", Ex.Message);
if (conn != null)
conn.Close();
}
return false;
}
private delegate void DisplayInfoDelegate(string Text);
private void HandleCallback(IAsyncResult result)
{
try
{
// Retrieve the original command object, passed
// to this procedure in the AsyncState property
// of the IAsyncResult parameter.
SqlCommand command = (SqlCommand)result.AsyncState;
int rowCount = command.EndExecuteNonQuery(result);
string rowText = " rows affected.";
if (rowCount == 1)
rowText = " row affected.";
rowText = rowCount + rowText;
// Call the procedure from the form's thread.
DisplayInfoDelegate del = new DisplayInfoDelegate(DisplayResults);
this.Invoke(del, rowText);
}
catch (Exception ex)
{
// Because you are now running code in a separate thread,
// if you do not handle the exception here, none of your other
// code catches the exception.
// You can create the delegate instance as you
// invoke it, like this:
this.Invoke(new DisplayInfoDelegate(DisplayResults),
String.Format("Ready(last error: {0}", ex.Message));
}
finally
{
bIsExecuting = false;
if (conn != null)
conn.Close();
}
}
private void DisplayResults(string Text)
{
this.toolStripStatusLabel1.Text = Text;
this.toolStripProgressBar1.Style = ProgressBarStyle.Blocks;
this.toolStripProgressBar1.Value = 100;
}
谢谢你的时间。
All, I have successfully used ADO.NET to make use of asynchronous SQL queries similar to the example below. In the example shown the method ExecNonQuery is being invoked from the UI thread. This works well, but I wondered how I would handle the callback if I were to call ExecNonQuery from a non-UI thread?
Note. Clearly, in such a case I would amend ExecNonQuery, so that such things as this.toolStripStatusLabel1.Text
were dealt with accordingly, or removed.
public bool ExecNonQuery(string strCmd, string strUserMsg = "")
{
try
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = strCmd;
cmd.CommandTimeout = 0;
bIsExecuting = true;
AsyncCallback callback = new AsyncCallback(HandleCallback);
cmd.BeginExecuteNonQuery(callback, cmd);
return true;
}
catch (Exception Ex)
{
bIsExecuting = false;
this.toolStripStatusLabel1.Text = String.Format("Ready (last error: {0})", Ex.Message);
if (conn != null)
conn.Close();
}
return false;
}
private delegate void DisplayInfoDelegate(string Text);
private void HandleCallback(IAsyncResult result)
{
try
{
// Retrieve the original command object, passed
// to this procedure in the AsyncState property
// of the IAsyncResult parameter.
SqlCommand command = (SqlCommand)result.AsyncState;
int rowCount = command.EndExecuteNonQuery(result);
string rowText = " rows affected.";
if (rowCount == 1)
rowText = " row affected.";
rowText = rowCount + rowText;
// Call the procedure from the form's thread.
DisplayInfoDelegate del = new DisplayInfoDelegate(DisplayResults);
this.Invoke(del, rowText);
}
catch (Exception ex)
{
// Because you are now running code in a separate thread,
// if you do not handle the exception here, none of your other
// code catches the exception.
// You can create the delegate instance as you
// invoke it, like this:
this.Invoke(new DisplayInfoDelegate(DisplayResults),
String.Format("Ready(last error: {0}", ex.Message));
}
finally
{
bIsExecuting = false;
if (conn != null)
conn.Close();
}
}
private void DisplayResults(string Text)
{
this.toolStripStatusLabel1.Text = Text;
this.toolStripProgressBar1.Style = ProgressBarStyle.Blocks;
this.toolStripProgressBar1.Value = 100;
}
Thanks for you time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
哪个线程运行
ExecNonQuery
对您的回调没有影响 -HandleCallback
仍将在线程池线程上运行。您已经发现需要进行的更改:如果 ExecNonQuery 未在 UI 线程上运行,则不要直接在 ExecNonQuery 中访问 UI 控件。
缺口
It makes no difference to your callback which thread runs
ExecNonQuery
-HandleCallback
will still be run on a thread pool thread.You have already spotted the change you need to make: don't access UI controls directly in
ExecNonQuery
if it is not being run on the UI thread.Nick