7

これはかなり単純なことです。しかし、私はこれを理解することができませんでした。

/// This section is located in the InitializeComponent() method
/// form's class, i.e. partial class frmMain { .... }
this.bgw = new System.ComponentModel.BackgroundWorker();
this.bgw.WorkerReportsProgress = true;
this.bgw.DoWork += new System.ComponentModel.DoWorkEventHandler(this.bgw_DoWork);
this.bgw.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.bgw_ProgressChanged);

/// This code is located in public partial class frmMain : Form { .... }
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 1; i <= 100; i++)
    {
        Thread.Sleep(100); // Wait 100 milliseconds
        //Console.WriteLine(i);
        bgw.ReportProgress(i);
    }
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // Update status label
    lblStatus.Text = e.ProgressPercentage.ToString();
}
// New code added to question after edit
public frmMain()
{
    InitializeComponent();
    bgw.RunWorkerAsync();
    // some more stuff...
}

バックグラウンド ワーカーは正しく実行されています。ただし、進行状況を正しく更新していません。DoWork イベントのコメント行のコメントを外すと、ステータスが正しく更新されていることがわかります。ただし、ProgressChanged イベントは、メイン スレッドのタスク (重いデータベースの計算処理) が終了するまでトリガーされません。

これは .NET Framework 4 を使用しており、Windows フォーム アプリケーションです。

編集

コードの場所については、上記のコードのコメントを参照してください。

いくつかの詳細

実行中のコードには、データベースでの複数のクエリの実行が含まれます。そのコードを開示する自由はありません。そのコードがどのように実行されているかについては、別の開発者から .dll を渡され、データベースにアクセスするときだけ使用するように言われたので、実際にはわかりません....

編集

「some more stuff」セクションのコードは次のように移動されました

private void frmMain_Load(object sender, EventArgs e)
{
   // some more stuff... aka run queries!
}
4

2 に答える 2

4

あなたのBackgroundWorkerコードは問題ありません。問題は、(同期データベース要求を実行することによって) UI スレッドをブロックしているコードが別の場所 (この場合はコンストラクターまたはFormLoad) にあることです。このコードが非 UI スレッドで実行されるようにするには、何かを行う必要があります。これは、既存のこれを使用してBackgroundWorker、他の長時間実行タスクを実行することを意味する可能性があります。Task.Factory.StartNewまたはその他のスレッド化メカニズムを使用して、UI 以外のスレッドで実行することもできます。

UI スレッドがブロックされていない場合、`ProgressChanged イベント ハンドラーで行われた更新が UI に反映されていることがわかります。

于 2012-08-20T20:47:58.187 に答える
2

@Servyはもちろん正しいです。

問題を再現するこのコードを使用したかっただけです。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        bgw.RunWorkerAsync();

        Task.Factory.StartNew(SomeMoreStuff);
    }

    private void SomeMoreStuff()
    {
        for (int i = 0; i < 5; i++)
        {
            Thread.Sleep(50);
            this.Invoke((Action)HogTheUIThread);
        }
    }

    private void HogTheUIThread()
    {
        Thread.Sleep(1000);
    }

    private void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 1; i <= 100; i++)
        {
            Thread.Sleep(100); // Wait 100 milliseconds
            //Console.WriteLine(i);
            bgw.ReportProgress(i);
        }
    }

    private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Update status label
        lblStatus.Text = e.ProgressPercentage.ToString();
    }
}
于 2012-08-20T21:06:44.597 に答える