0

C# 4.0 で並列プログラミングをテストするプログラムを作成しました。しかし、問題があり、その理由がわかりません。

メソッドを書きます

    private void compute(int startValue, int endValue, ConcurrentBag<Pair> theList)
    {
        try
        {
            Task computation = Task.Factory.StartNew(() => { findFriendlyNumbers(startValue, endValue, theList, tokenSource.Token); }, tokenSource.Token);
            Task.WaitAll(computation);
            StringBuilder builder = new StringBuilder();
            foreach (Pair p in theList)
            {
                builder.AppendLine(p.ToString());
            }

            this.textBlockResult.Dispatcher.Invoke(new Action(() =>
            {
                this.textBlockResult.Text = builder.ToString();
                this.progressBar1.Visibility = System.Windows.Visibility.Hidden;
            }));
        }
        catch (AggregateException aEx)
        {
            MessageBox.Show("Entering");  //For debug, but never runs
            aEx.Handle(handleCancelling);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

別のスレッド (UI スレッド以外) で実行されます。

そして機能(簡略化)

        private void findFriendlyNumbers(int start, int end, ConcurrentBag<Pair> list, CancellationToken token)
    {
        //some initialization and computation

        for (int i = start; i <= end; i++)
        {
            //check whether it's cancelled
            token.ThrowIfCancellationRequested();

            //some computation
        }
    }

問題は、tokenSource がキャンセルされると、catch ブロックが存在しないかのように、"OperationCanceledException is not handler by user code" というエラーが発生することです。私のコードは教科書や MSDN のコードと似ているため、その理由はわかりません。

ありがとうございました。

編集: 私は実際に 1 か月も経たないうちに同様のプログラムを作成しましたが、そのときはすべて問題ありませんでした。今日、もう一度実行しようとしましたが、同じ問題が発生しました。プログラムの終了後に Microsoft Visual Web Developer 2010 Express をインストールしましたが、これが原因かどうかわかりません。わからない、同じコード、異なる結果。

編集:私はこの問題について考え、どこが間違っているかを見つけました。以前は「デバッグなしで実行」を使用していましたが、現在はデバッグを使用しています。デバッグなしで実行すると、問題が解決します。また、デバッグが「デバッグなしで実行」と異なる理由を教えていただければ幸いです。

4

1 に答える 1

1

TaskFactory.StartNewキャンセルトークンをメソッドに渡します。これによりTask、エラーではなくキャンセルの兆候として、特別に扱われます。

トークンをパラメータとしてに渡さない場合TaskFactory.StartNew、エラーとして扱われ、キャッチされます。パラメータとして保持する場合Task.IsCanceledは、例外の代わりにを使用してキャンセルをチェックする必要があります。

補足:InvokeUIスレッドとの同期には使用しないことをお勧めします。ブログにUIの進行状況の更新を適切に行うオブジェクトの例があります。Task

于 2010-08-23T03:01:30.603 に答える