【发布时间】:2015-07-29 14:04:23
【问题描述】:
我一直在使用 TPL 在非 UI 线程中运行数据库提取,从而允许 UI 在它们发生时继续进行。调用下面示例中的代码来填充主详细信息视图中的详细信息窗格。主窗格中有一个树视图,根据单击的节点获取不同的数据。 UI 允许用户取消提取,如果用户在提取处于活动状态时选择了不同的节点,则会自动取消提取。这是我用来执行此操作的代码:
Protected Overrides Sub FetchSummary()
If DBKey.PresentAndSet(DataKey) Then
_view.BeginDataFetch()
' Cancel any active refresh
If TaskCancelTokenSource IsNot Nothing Then TaskCancelTokenSource.Cancel()
TaskCancelTokenSource = New CancellationTokenSource
Dim ctok = TaskCancelTokenSource.Token
Dim dataTask = New Task(Of IEnumerable(Of IAssignSailingPart.ISummary))(Function() FetchsummaryData(Context, DataKey), ctok)
Dim uiSyncContext = TaskScheduler.FromCurrentSynchronizationContext
dataTask.ContinueWith(Sub(dt) _view.Data = dt.Result, ctok, TaskContinuationOptions.OnlyOnRanToCompletion, uiSyncContext)
dataTask.ContinueWith(Sub(dt) _view.FailDataFetch("There was an error fetching the data, try refreshing"), Nothing, TaskContinuationOptions.OnlyOnFaulted, uiSyncContext)
dataTask.ContinueWith(Sub(dt) _view.Data = New List(Of IAssignSailingPart.ISummary), Nothing, TaskContinuationOptions.OnlyOnCanceled, uiSyncContext)
dataTask.Start()
End If
End Sub
因此,为了启动任务,我们调用一个函数来查询数据库以获取我们的结果。成功时我们将其发送到视图,取消时我们将空数据集发送到视图,失败时我们告诉用户尝试刷新。
这一切似乎工作正常。用户对响应能力等感到满意。尽管数据库服务器遇到了一些不相关的问题,但我们最近遇到了一些问题。当在应用程序的编译版本(而不是在 IDE 中)上获取失败时,它会在实际失败发生后不久以未捕获的聚合异常终止应用程序。我已经对此进行了一些研究,并了解(或认为我这样做)在任务被垃圾收集时,异常被抛出在不同的线程上。
我的问题是我应该如何调整代码来正确处理这个问题?这适用于使用 .Net 4.0 的 Windows 窗体应用程序。
【问题讨论】:
标签: .net vb.net winforms task-parallel-library