我使用ContinueWith運行一項任務,該任務執行雙重任務:如果任務成功完成,則處理結果,如果發生錯誤則處理任何異常。但是,下面的代碼將不能正確地處理任何異常,並將其註冊爲unhandeled並帶來降低程序(張貼所以有些縮短,可能不是完美的):TPL任務繼續執行結果和異常導致未處理的異常
void _SqlServerDatabaseListLoader()
{
_ClearSqlHolders(true, false);
_SqlConnectionStringHolder.Database = "master";
if (_SqlConnectionStringHolder.IsComplete)
{
//Could time out put on its own thread with a continuation back on the UI thread for the popup
_TaskCanceller = new CancellationTokenSource();
_TaskLoader = Task.Factory.StartNew(() =>
{
IsLoadingSqlServerDatabaseList = true;
using (SqlConnection con = new SqlConnection(_SqlConnectionStringHolder))
{
// Open connection
con.Open(); //If this cause an error (say bad password) the whole thing bombs
//create a linq connection and get the list of database names
DataContext dc = new DataContext(con);
return new ObservableCollection<string>(dc.ExecuteQuery<string>("select [name] from sys.databases").ToObservableCollection());
}
}).ContinueWith(antecendant => _SqlServerDatabaseListLoaderComplete(antecendant.Result, antecendant.Exception),
_TaskCanceller.Token,
TaskContinuationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
}
}
void _SqlServerDatabaseListLoaderComplete(ObservableCollection<string> DatabaseList, AggregateException ae)
{
//Just show the first error
if (ae != null)
ToolkitDialog.ShowException(ae.InnerExceptions[0], ToolkitDialogType.Error, CustomDialogButtons.OK, "Error:", "Database List Error");
if(DatabaseList != null)
SqlServerDatabaseList = DatabaseList
//Set the running indicator
_TaskLoader = null;
_TaskCanceller = null;
IsLoadingSqlServerDatabaseList = false;
}
我使用TaskContinuationOptions.None拉這一關,我認爲這是正確的。這在基類中聲明這上面的類繼承自:
protected Task _TaskLoader;
protected CancellationTokenSource _TaskCanceller;
如果我是不會導致錯誤的情形下運行,一切順利,我得到我的數據庫清單。但是,如果出現錯誤,說某人爲此SQL Server登錄憑據提供了錯誤的密碼,則不會處理該錯誤。
但如果我刪除傳遞Result參數的選項,一切正常,因爲它應該和異常引起:
void _SqlServerDatabaseListLoader()
{
_ClearSqlHolders(true, false);
_SqlConnectionStringHolder.Database = "master";
if (_SqlConnectionStringHolder.IsComplete)
{
//Could time out put on its own thread with a continuation back on the UI thread for the popup
_TaskCanceller = new CancellationTokenSource();
_TaskLoader = Task.Factory.StartNew(() =>
{
IsLoadingSqlServerDatabaseList = true;
using (SqlConnection con = new SqlConnection(_SqlConnectionStringHolder))
{
// Open connection
con.Open();
//create a linq connection and get the list of database names
DataContext dc = new DataContext(con);
//HAVE TO SET IN THE THEAD AND NOT RETURN A RESULT
SqlServerDatabaseList = new ObservableCollection<string>(dc.ExecuteQuery<string>("select [name] from sys.databases").ToObservableCollection());
}
}).ContinueWith(antecendant => _SqlServerDatabaseListLoaderComplete(antecendant.Exception),
_TaskCanceller.Token,
TaskContinuationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
}
}
void _SqlServerDatabaseListLoaderComplete(AggregateException ae)
{
//Just show the first error
if (ae != null)
ToolkitDialog.ShowException(ae.InnerExceptions[0], ToolkitDialogType.Error, CustomDialogButtons.OK, "Error:", "Database List Error");
//Set the running indicator
_TaskLoader = null;
_TaskCanceller = null;
IsLoadingSqlServerDatabaseList = false;
}
我認爲我不完全理解TPL是怎麼想的工作。我試圖創造更多的一個ContinueWith,這似乎沒有什麼區別。謝謝你的幫助。
謝謝里德。很有意思。我嘗試了,實際上並沒有得到它去。感謝關於通過整個任務但同樣的事情的想法。它不喜歡「.Result」 - 它給出了它不存在的設計時錯誤(兩種情況)。真奇怪。如果我使用_TaskLoader,它會給我簽名錯誤,說它不能將任務投射到任務>。如果我設置了「受保護的任務> _TaskLoader」,我仍然收到錯誤消息。但是如果我做了「var x = Task > .Factory.StartNew(()=> ....」它可以。 –
Ernie
@Ernie之前,你正在爲你的* continuation設置_TaskLoader *而不是原始任務。這可能就是爲什麼你有類型不匹配 –
AHHHH ......就是它裏德!我認爲這一直是我的問題,包括當我試圖在發佈之前用兩個ContinueWith發佈時分解它。 。感謝所有的幫助! – Ernie