我有一個長時間運行的操作,我正在使用TPL在後臺線程上。我目前的工作,但我很困惑,我應該在取消請求期間處理我的AggregateException
。如何正確取消TPL任務(續)
在按鈕單擊事件,我開始我的過程:
private void button1_Click(object sender, EventArgs e)
{
Utils.ShowWaitCursor();
buttonCancel.Enabled = buttonCancel.Visible = true;
try
{
// Thread cancellation.
cancelSource = new CancellationTokenSource();
token = cancelSource.Token;
// Get the database names.
string strDbA = textBox1.Text;
string strDbB = textBox2.Text;
// Start duplication on seperate thread.
asyncDupSqlProcs =
new Task<bool>(state =>
UtilsDB.DuplicateSqlProcsFrom(token, mainForm.mainConnection, strDbA, strDbB),
"Duplicating SQL Proceedures");
asyncDupSqlProcs.Start();
//TaskScheduler uiThread = TaskScheduler.FromCurrentSynchronizationContext();
asyncDupSqlProcs.ContinueWith(task =>
{
switch (task.Status)
{
// Handle any exceptions to prevent UnobservedTaskException.
case TaskStatus.Faulted:
Utils.ShowDefaultCursor();
break;
case TaskStatus.RanToCompletion:
if (asyncDupSqlProcs.Result)
{
Utils.ShowDefaultCursor();
Utils.InfoMsg(String.Format(
"SQL stored procedures and functions successfully copied from '{0}' to '{1}'.",
strDbA, strDbB));
}
break;
case TaskStatus.Canceled:
Utils.ShowDefaultCursor();
Utils.InfoMsg("Copy cancelled at users request.");
break;
default:
Utils.ShowDefaultCursor();
break;
}
}, TaskScheduler.FromCurrentSynchronizationContext()); // Or uiThread.
return;
}
catch (Exception)
{
// Do stuff...
}
}
在該方法中DuplicateSqlProcsFrom(CancellationToken _token, SqlConnection masterConn, string _strDatabaseA, string _strDatabaseB, bool _bCopyStoredProcs = true, bool _bCopyFuncs = true)
我
DuplicateSqlProcsFrom(CancellationToken _token, SqlConnection masterConn, string _strDatabaseA, string _strDatabaseB, bool _bCopyStoredProcs = true, bool _bCopyFuncs = true)
{
try
{
for (int i = 0; i < someSmallInt; i++)
{
for (int j = 0; j < someBigInt; j++)
{
// Some cool stuff...
}
if (_token.IsCancellationRequested)
_token.ThrowIfCancellationRequested();
}
}
catch (AggregateException aggEx)
{
if (aggEx.InnerException is OperationCanceledException)
Utils.InfoMsg("Copy operation cancelled at users request.");
return false;
}
catch (OperationCanceledException)
{
Utils.InfoMsg("Copy operation cancelled at users request.");
return false;
}
}
在按鈕的Click事件(或使用delegate
(buttonCancel.Click + =代理{/ 取消任務 /} ) I cancel the
任務如下:
private void buttonCancel_Click(object sender, EventArgs e)
{
try
{
cancelSource.Cancel();
asyncDupSqlProcs.Wait();
}
catch (AggregateException aggEx)
{
if (aggEx.InnerException is OperationCanceledException)
Utils.InfoMsg("Copy cancelled at users request.");
}
}
這樣捕獲OperationCanceledException
罰款方法DuplicateSqlProcsFrom
並打印我的消息,但在asyncDupSqlProcs.ContinueWith(task => { ... });
提供的回撥提供task.Status
以上總是RanToCompletion
;它應該被取消!
在這種情況下捕獲和處理Cancel()
任務的正確方法是什麼?我知道如何在this example from the CodeProject和examples on MSDN中顯示的簡單情況下完成這項工作,但在運行延續時我很困惑。
在這種情況下如何捕獲取消任務以及如何確保task.Status
得到正確處理?
謝謝你。它真的有幫助。我已經到了從'DuplicateSqlProcsFrom'方法中刪除handeling的階段,但仍然試圖在其他地方捕獲它。 – MoonKnight 2012-03-13 13:59:25
我按照你的建議完成了,但在我的延續方法中,我只能得到'TaskStatus.Faulted'條件,從來沒有'TaskStatus.Cancelled'。你知道這可能是爲什麼嗎? – MoonKnight 2012-03-13 14:12:49
我已經爲此答案添加了解釋和解決方案。 – shambulator 2012-03-13 15:18:37