在进行测试以查看它在不同操作系统上的响应方式时,我在 winForms 应用程序中遇到了一个奇怪的行为。
抛出未处理的长时间运行的操作AggregateException
(在 XP 32 位机器上测试时)是 WCF(使用basicHttpBinding
和Streamed
传输模式)客户端更新过程的一部分。该结构类似于以下代码片段。为了清楚起见,我省略了 WCF 异常处理:
var tsUIthread = TaskScheduler.FromCurrentSynchronizationContext();
int filesCount = 0;
List<MessageContract> files;
private void Update()
{
var cTokenDownloadFiles = new CancellationTokenSource();
var cTokenUpdateDatabases = new CancellationTokenSource();
var task1CheckForNewFiles = Task.Factory.StartNew(() =>
{
filesCount = proxy.GetFiles();
If(filesCount == 0)
{
cTokenDownloadFiles.Cancel();
cTokenUpdateDatabases.Cancel();
}
else
files = new List<MessageContract>();
});
var task2UpdateControls = task1CheckForNewFiles.ContinueWith(result =>
{
UpdateControlsBeforeDownload();
}, CancellationToken.None, TaskContinuationOptions.None, tsUIthread);
var task3DownloadFiles = task2.ContinueWith(result =>
{
for(int i = 0; i< filesCount; i++)
{
try
{
files.Add(proxy.DownloadFile());
}
catch(IOException)
{
cTokenUpdateDatabases.Cancel();
Task.Factory.StartNew(() => ResetControls,
CancellationToken.None, TaskCreationOptions.None, tsUIthread);
retryUpdateTimer.Start(); // System.Windows.Forms.Timer
return;
}
}
}, cTokenDownloadFiles.Token);
var task4UpdateDatabases = task3DownloadFiles.ContinueWith(result =>
{
UpdateDatabases();
},cTokenUpdateDatabases.Token);
var task5UpdateControls = task4UpdateDatabases.ContinueWith(result =>
{
UpdateControlsOnUpdateFinished();
}, CancellationToken.None, TaskContinuationOptions.None, tsUIthread);
}
你会注意到我将proxy.DownloadFile()
方法包装在一个 try-catch 块中,我在其中捕获了一个IO.IOException
. 正如我在文章开头所说的那样,我的 WCF 服务使用Streamed
传输模式,basicHttpBinding
因此当操作开始后由于某种原因与服务器的连接丢失时,我需要捕获这种类型的异常。我在 catch 语句中所做的只是取消数据库更新任务,将 UI 控件重置为其主要值,并Interval
在几秒钟内启动 System.Windows.Forms.Timer,Update()
如果客户端有互联网,它将再次执行该方法连接性。
虽然整个过程在我的开发环境(Windows7 32 位机器)上按预期工作IOException
,但当我在 Windows XP 32 位机器上测试我的 winforms 应用程序时,未处理AggregateException
的 at 会System.Threading.Tasks.ExceptionHolder.Finalize()
终止应用程序。
有没有人经历过类似的事情?怎么可能只在 XP 机器上抛出异常?我还没有在其他环境中测试过它。实际代码包含更多任务和延续,调用下游业务组件,当涉及到带有延续意大利面的任务异常处理时,我有点迷失了。你能给我一些我应该如何构建异常处理的例子吗?