1

サービスを呼び出すいくつかのコードに取り組んでいます。このサービス コールは失敗する可能性があります。失敗した場合は、システムが機能するか時間が経過するまで再試行する必要があります。

次のコードが正しく機能していないように見えるため、どこが間違っているのか疑問に思っています...ランダムに1〜4回のループしか行いません...

protected virtual void ProcessAsync(object data, int count)
{
    var worker = new BackgroundWorker();
    worker.DoWork += (sender, e) =>
    {
        throw new InvalidOperationException("oh shiznit!");
    };
    worker.RunWorkerCompleted += (sender, e) =>
    {
        //If an error occurs we need to tell the data about it
        if (e.Error != null)
        {
            count++;
            System.Threading.Thread.Sleep(count * 5000);
            if (count <= 10)
            {
                if (count % 5 == 0)
                    this.Logger.Fatal("LOAD ERROR - The system can't load any data", e.Error);
                else
                    this.Logger.Error("LOAD ERROR - The system can't load any data", e.Error);
                this.ProcessAsync(data, count);
            }
        }
    };
    worker.RunWorkerAsync();
}

乾杯アンソニー

アップデート:

代わりに ThreadPool.QueueUserWorkItem を使用するようにコードを切り替えました...これを行ってから、問題はなくなり、意味的には同じことができます。助けてくれてありがとう。

4

4 に答える 4

4

私はあなたのコードをわずかに変更しましたが、10回の反復(VS 2008 Express)を実行しても問題はありません。これは実際のコードですか?そうでない場合は、問題を再現するのに十分な量を送信したと思いますか?

あえて推測すると、送信しているカウントはさまざまcount % 5 > 0であり、例外がスローされていると言えますLogger.Fatal

private void button1_Click(object sender, EventArgs e)
{
    ProcessAsync("beer", 1);
}

protected virtual void ProcessAsync(object data, int count)
{
    var worker = new BackgroundWorker();
    worker.DoWork += (sender, e) =>
    {
        throw new InvalidOperationException("oh shiznit!");
    };
    worker.RunWorkerCompleted += (sender, e) =>
    {
        //If an error occurs we need to tell the data about it
        if (e.Error != null)
        {
            count++;
            //System.Threading.Thread.Sleep(count * 5000);
            if (count <= 10)
            {
                if (count % 5 == 0)
                    this.Logger.Fatal("LOAD ERROR - The system can't load any data - " + count.ToString(), e.Error);
                else
                    this.Logger.Error("LOAD ERROR - The system can't load any data - " + count.ToString(), e.Error);
                this.ProcessAsync(data, count);
            }
        }
    };
    worker.RunWorkerAsync();
}

SomeLogger Logger = new SomeLogger();

class SomeLogger
{
    public void Fatal(string s, Exception e)
    {
        System.Diagnostics.Debug.WriteLine(s);
    }

    public void Error(string s, Exception e)
    {
        System.Diagnostics.Debug.WriteLine(s);
    }
}

編集: 提案
への呼び出しの周りに try-catch を配置し、Logger.Fatal何が起こるかを確認します。

編集: 別の提案
として、私たちが支援するのに十分なコードを共有していないと思われます。ここで成功するための鍵は、失敗を示すのに十分なコードしかないダミー プロジェクトで問題を切り分けることです。それができれば、おそらくここに質問として投稿する必要はないでしょう...

私の仮定から始めることができ、これがうまく機能することがわかるはずです。次に、一般化されたコードを実際に使用しているものに変更し始めます (Logger.Fatal の実際の実装から始めます)。エラーはすぐに明らかになるでしょう。

于 2010-05-11T04:50:06.110 に答える
1

明確な理由はわかりません。ただし、RunWorkerCompleted イベントは通常、UI スレッドで実行されます。そして55秒も吊るしてください。それは望ましいことではありません。

try/catch ブロックを使用して DoWork メソッドをループしない理由を考えることができる理由はありません。

于 2010-05-11T04:53:44.573 に答える
1

これは、私が見た中で最も奇妙な再試行メカニズムに違いありません。よりきれいなものを作ることはできますか?単純で保守が容易でない限り、再帰呼び出しは避けてください。間違いにつながりやすいためです。

于 2010-05-11T04:31:19.247 に答える
0

本当に悪いことが 1 つあります。

あなたの中でRunWorkerCompleted()a を呼び出しますThread.Sleep()。この関数は GUI スレッド内で処理されるため、アプリケーションがフリーズします。

Thread.Sleep()すべてのイベントが GUI スレッド内で処理されるため、BackgroundWorker のイベント内で呼び出さないでください。

したがって、これは現在の問題に対する本当の解決策ではないかもしれませんが、気にする必要があることは間違いありません。

更新
一定時間後に何かを開始するには、さまざまな タイマー クラスを調べる必要があります。それぞれに長所と短所があります。詳細については、この記事をご覧ください。

于 2010-05-11T06:33:43.450 に答える