TPL如何执行';回电';
本文关键字:回电 执行 何执行 TPL | 更新日期: 2023-09-27 18:27:04
我有一个小型应用程序,它需要测试多个连接的SQL连接字符串(每个连接一次完成一个)。要做到这一点,我临时设置ConnectionTimeout = 5
,以避免在连接无效时长时间等待,并设置ConnectionTimeout = 0
(永远等待)。
为了避免在尝试Open()
连接不好时UI挂起(即使使用ConnectionTimeout = 5
,等待SqlException
的时间也可能长达20秒),我想使用任务并行库(TPL)在单独的线程上运行测试。所以我开始了我的新线程:
Task<bool> asyncTestConn = Task.Factory.StartNew<bool>
(() => TestConnection(conn, bShowErrMsg));
return asyncTestConn.Result;
问题是,这仍然锁定了UI(很明显),因为它在返回到调用者之前正在等待结果。如何允许代码将控制权返回到UI(释放GUI),同时从异步Task
获得最终结果?
此外,在Task
中,我可以合法地执行MessageBox.Show("Some message")
吗?这对BackgroundWorkers
不起作用,并且该池线程默认情况下是后台线程;然而,这似乎不是一个问题。谢谢你抽出时间。
对于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());
你是对的,这就是等待发生的地方:
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也应该是可能的。
但是你延长了任务的寿命,这不是一个好主意。