1

私は私のアプリケーションでタイマーの世話をするバックグラウンドワーカーを持っています。これはコードです:

    protected override void OnLoad(EventArgs e)
    {
        // Inizializzo il backgroundworker 
        bgwTimer.WorkerReportsProgress = true;
        bgwTimer.WorkerSupportsCancellation = true;
        bgwTimer.DoWork += (bgwTimer_DoWork);
        bgwTimer.RunWorkerCompleted +=(bgwTimer_RunWorkerCompleted);
        bgwTimer.ProgressChanged += (bgwTimer_ProgressChanged);
    }

    void bgwTimer_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        throw new NotImplementedException();
    }

    void bgwTimer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        throw new NotImplementedException();
    }

基本的に、イベント「ProgressChanged」は発生しないため、プログレスバーのステータスを更新できません。イベントDoWorkは、次のメソッドにリンクされています。

    void bgwTimer_DoWork(object sender, DoWorkEventArgs e)
    {
        int i = 0;
        if (bgwTimer.CancellationPending)
        {
            e.Cancel = true;
        }
        else
        {
            while (bgwTimer.IsBusy)
            {                
                Thread.Sleep(1000);
                bgwTimer.ReportProgress(i);
                refreshTimer();
            }
        }
    }

私の側では、コードは見栄えがよく、正常に実行されます。ご覧のとおり、ReportProgressメソッドは呼び出されますが、イベントは発生しません。ヒントはありますか?

更新:おっと!イベント「bgwTimer_ProgressChanged」は、イベントの宣言の直後にRunWorkerAsyncを実行した場合にのみ発生することがわかりました。基本的に:

bgwTimer.ProgressChanged + =(bgwTimer_ProgressChanged); bgwTimer.RunWorkerAsync(); //これは機能します!

ユーザーがボタンを押したときにワーカーを実行するため、イベントはトリガーされません。


クリックイベントボタンのコードは次のとおりです。

    private void btnNext_Click(object sender, EventArgs e)
    {            
        this.TopMost = true;
        btnNext.Enabled = false;
        progressBar1.Step = 0;

        if (_bgwTimer.IsBusy)
            _bgwTimer.CancelAsync();
        else
            _bgwTimer.RunWorkerAsync();
    }
4

4 に答える 4

3

ブレークポイント、またはのDebug.Print直前System.Windows.Forms.Messageboxにブレークポイントを設定して、bgwTimer.ReportProgress(i)実際にwhileループに入っていることを確認します。

BackgroundWorkerこれは実際にはタイマーではないことに注意してください。これは、ユーザーインターフェイスにスレッドセーフな呼び出しレイヤーを提供するスレッドのラッパーです。

ループの外側ではなくif (bgwTimer.CancellationPending) { }、ループの内側にいる必要がありwhileます。現在のコードで一度だけチェックされます。

DoWorkイベントハンドラー内にいる場合は、定義上、非同期プロセスを実行しているためIsBusy、(MSDNのドキュメントによると)常にtrueである必要があるためwhile、無限ループになることに注意してください。ただし、デバッガーで確認してください。

于 2012-10-16T14:47:49.407 に答える
3

の値は常にゼロであるため、イベントは発生しませんi。これは文書化されていないので便利ですが、しばらく前にバックグラウンドワーカーを作成したときに同じことがわかりました。

于 2012-10-16T14:53:02.423 に答える
2

あなたは労働者を始めるのを忘れました。次の行をOnLoad()メソッドに追加します。

   bgwTimer.RunWorkerAsync();
于 2012-10-16T14:56:00.347 に答える
0

DoWork-Methodで、bgwTimerを((BackgroundWorker)sender)に置き換えます。多分これが問題です

于 2012-10-16T14:48:33.067 に答える