我有一个小应用程序需要为多个连接测试SQL连接字符串(每个连接一次一个地完成)。为此,我暂时设置ConnectionTimeout = 5
,以避免在连接无效时等待很长时间,并ConnectionTimeout = 0
(等待永远),比方说。
为了避免在我们尝试Open()
错误连接时悬挂用户界面(即使使用ConnectionTimeout = 5
,等待SqlException
的时间可能长达20秒),我想要运行使用任务并行库(TPL)在单独的线程上进行测试。所以我将我的新主题分拆出来:
Task<bool> asyncTestConn = Task.Factory.StartNew<bool>
(() => TestConnection(conn, bShowErrMsg));
return asyncTestConn.Result;
问题是这仍然是锁定UI(显然),因为它在返回调用者之前等待结果。如何在从异步Task
获取最终结果的同时允许代码将控制权返回给UI(释放GUI)?
另外,在Task
MessageBox.Show("Some message")
范围内我可以合法地BackgroundWorkers
吗?这对{{1}}不起作用,默认情况下,此池化线程是后台线程;但它似乎不是一个问题。谢谢你的时间。
答案 0 :(得分:5)
对于TPL,ContinueWith
正是您想要的。扩展Henk的答案:
var asyncTestConn = Task.Factory.StartNew(() => TestConnection(conn, bShowErrMsg));
// Henk's "MyFinishCode" takes a parameter representing the completed
// or faulted connection-testing task.
// Anything that depended on your "return asyncTestConn.Result;" statement
// needs to move into the callback method.
asyncTestConn.ContinueWith(task =>
{
switch (task.Status)
{
// Handle any exceptions to prevent UnobservedTaskException.
case TaskStatus.Faulted: /* Error-handling logic */ break;
case TaskStatus.RanToCompletion: /* Use task.Result here */ break;
}
},
// Using this TaskScheduler schedules the callback to run on the UI thread.
TaskScheduler.FromCurrentSynchronizationContext());
答案 1 :(得分:4)
你是对的,这是等待发生的地方:
return asyncTestConn.Result;
您可以在TestConnection()的尾部构建完成代码或使用Continuation:
// untested
//Task<bool> asyncTestConn = Task.Factory.Create<bool> (
Task<bool> asyncTestConn = new Task<bool> (
() => TestConnection(conn, bShowErrMsg));
asyncTestConn.ContinueWith(MyFinishCode);
asyncTestConn.Start()
我可以合法地
MessageBox.Show("Some message")
吗?
实际上是,MessageBox是线程安全的。也应该可以从Bgw。
但是你要延长任务的寿命,这不是一个好主意。