0

以下は私のコーディングです:

    Form2 msgForm;
    private void button3_Click_1(object sender, EventArgs e)
    {

        bw.WorkerReportsProgress = true;
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

        msgForm = new Form2();

        try
        {
            bw.RunWorkerAsync();

            msgForm.ShowDialog();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        // Coding that transmit protocol and will last around 2 minutes.
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        msgForm.Close();
    }

ボタンをクリックするたびにバックグラウンド ワーカー メソッドを使用して、約 2 分間続くプロトコルを送信します。送信中、From2 は「お待ちください」と表示します。

しかし、このコーディングの使用には問題があります。問題は、ボタンを初めてクリックすると、プロトコルが1回送信されるようなものです。その後、2回目でもう一度クリックすると、プロトコルが2回送信されます。その後、3 回目のクリックで、プロトコルを 3 回送信します....というように続きます。ボタンをクリックするたびに、送信のプロトコルの回数が増えます。

ボタンをクリックするたびに void bw_DoWork のコーディングが 1 回だけ実行されるのではないですか?

コーディングに何か問題がありますか?

4

4 に答える 4

6

You're appending an additional handler every time you click, and then it's run along with everything you added before, which stays where it is (because the object is still there, you're re-using it).

To solve this, you need to either:

  • Move the declaration of the background worker inside the method (so it's new every time, with only one DoWork handler

Like this:

private void button3_Click_1(object sender, EventArgs e)
{
    BackgroundWorker bw = new BackgroundWorker();
    // rest of your code
}
  • Move the .DoWork += ... which appends the handler in the constructor of the class

It mostly depends on if you use that worker somewhere else.

于 2012-09-20T07:13:47.783 に答える
0

コードを送信する前に、まずリスト/コレクションがクリアであることを確認してください。次に、ソース コードで BreakPoint を使用します。ShowDialog を使用しているため、BackgroundWorker を 2 回以上実行できないことに注意してください。

于 2012-09-20T07:18:12.097 に答える
0

クリックするたびに新しいワーカーが開始されるようです。この動作を回避するには、ワーカーがビジーかどうかを確認してから、再度開始してください。

try
{
    if (!bw.IsBusy)
        bw.RunWorkerAsync();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

また、バックグラウンドワーカーがジョブを実行している間はボタンを無効にbutton3.Enabled = false;し、メソッドでボタンを再度有効にしてbw_RunWorkerCompleted、プロセスが完了するまで待つ必要があり、再度クリックできないことをユーザーに理解させます。

于 2012-09-20T07:15:28.813 に答える
0

ワーカーがビジーかどうかを確認します。

    if (!bw.IsBusy)         
    bw.RunWorkerAsync(); 

また、ボタンを無効にして、プロセスの実行中にテキストを「実行中」などに変更します。

bw_RunWorkerCompleted メソッド イベント呼び出しを使用して、ボタンを再度有効にし、テキストを変更します。このメソッドは UI と同じスレッドで実行されるため、クロススレッドの問題はありません。

デザインで、「お待ちください」通知用に別のフォームを表示しているのはなぜですか? 非同期プロセスが開始される前に既存のフォームのラベルを更新することをお勧めします (クロス スレッド UI の問題ではありません)。または、その後更新する必要がある場合は、次を使用できます。

lblNotify.Invoke(new Action(() => lblNotify.Text = @"Please wait"));

上記により、メインスレッドでリクエストを実行できるようになります。

于 2012-09-20T09:47:29.507 に答える