1

二重の義務を引き出す ContinueWith を使用してタスクを実行しています。タスクが正常に完了した場合は結果を処理し、エラーが発生した場合は例外を処理します。ただし、以下のコードは例外を適切に処理せず、未処理として登録し、プログラムをダウンさせます (投稿のために多少短縮されているため、完全ではない可能性があります)。

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 を作成しようとしましたが、違いはないようです。助けてくれてありがとう。

4

1 に答える 1