web-dev-qa-db-ja.com

C#バックグラウンドワーカーがDoWorkでe.Resultを設定し、WorkCompletedで値を取得する

C#2008 SP1

バックグラウンドワーカーを使用しています

条件の1つが失敗した場合、e.cancelをtrueに設定し、文字列をe.resultに割り当てます。すべてがそこで機能します。

ただし、workCompletedが起動すると、e.Resultをテストすると、「e.resultはsysteminvalidoperationタイプの例外をスローします」という例外が発生します。

グローバル変数を使用してDoWorkに設定し、完了した作業を比較できると思います。しかし、これはスレッドセーフではないかもしれません。

E.Resultでこれを取得する理由と、これを解決するにはどうすればよいですか?

どうもありがとう、

    private void bgwPrepareCall_DoWork(object sender, DoWorkEventArgs e)
    {
        // Check to see if the called number is blocked. 
        // If the nubmer is blocked display error message.
        if (this.IsNoGateway(sipUsername, statusDisplay1.PhoneNumber))
        {
            // this.SetIdleState(DialerErrorMessage.GetErrorDescription(12));
            e.Cancel = true;
            e.Result = "NoGateway";
            return;
        }

        if (!this.IsInvalidTelephoneNumber(sipUsername, statusDisplay1.PhoneNumber))
        {
            // this.SetIdleState(DialerErrorMessage.GetErrorDescription(13));
            e.Cancel = true;
            e.Result = "InvalidNumber";
            return;
        }
    }

    private void bgwPrepareCall_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            if (e.Cancelled)
            {
                // Failed
                switch (e.Result.ToString())
                {
                    case "NoGateway":
                        Console.WriteLine("NoGateway: [ Failed ]");
                        break;

                    case "InvalidNumber":
                        Console.WriteLine("InvalidNumber: [ Failed ]");
                        break;

                    default:
                        Console.WriteLine("Unknown");
                        break;
                }
            }
            if (!e.Cancelled)
            {
                // Successfull
                Console.WriteLine("NoGateway: [ ok ]");    
                Console.WriteLine("InvalidNumber: [ ok ]");
            }
        }
        else
        {
            Console.WriteLine("PrepareCall Failed: [ " + e.Error.Message + " ]");
        }
    }
17
ant2009

から [〜#〜] msdn [〜#〜]

操作が正常に完了し、その結果がDoWorkイベントハンドラーに割り当てられている場合は、RunWorkerCompletedEventArgs.Resultプロパティを介して結果にアクセスできます。

および

RunWorkerCompletedイベントハンドラーは、Resultプロパティにアクセスする前に、必ずErrorプロパティとCanceledプロパティを確認する必要があります。例外が発生した場合、または操作がキャンセルされた場合、Resultプロパティにアクセスすると例外が発生します。

したがって、それがしない正常に完了した場合(つまり、キャンセルした場合)、機能しないように見えます。おそらく、中止の場合の結果として(成功として)キャンセルの詳細を返し、完了ハンドラーの違いを検出することを検討しますか?

27
Marc Gravell

Resultプロパティは、completed操作の結果を表すことを目的としています。 Cancelをtrueに設定しました。これは、操作がキャンセルされたため、結果が得られないことを意味します。

「何かが間違っていたために中止しました」を結果にエンコードするか、代わりに結果のErrorプロパティとして設定される例外をスローする必要があるようです-Cancelは通話が外部からキャンセルされたことにワーカーが気付いた場合に設定されます。

RunWorkerCompletedEventArgs.Result 状態:

RunWorkerCompletedイベントハンドラーは、Resultプロパティにアクセスする前に、必ずErrorプロパティとCanceledプロパティを確認する必要があります。例外が発生した場合、または操作がキャンセルされた場合、Resultプロパティにアクセスすると例外が発生します。

ドキュメントの「例外」の部分には、Cancelledがtrueの場合に例外がスローされることも記載されています。

19
Jon Skeet

これはおそらく、コードが作業を完了するのではなくキャンセルするためです。したがって、if(!e.Cancel)ブランチの結果にアクセスしてみてください。

2
parapet