WPFバックグラウンドワーカーの使用方法


177

私のアプリケーションでは、一連の初期化手順を実行する必要があります。これらの手順が完了するまでに7〜8秒かかり、その間にUIが応答しなくなります。これを解決するには、別のスレッドで初期化を実行します。

public void Initialization()
{
    Thread initThread = new Thread(new ThreadStart(InitializationThread));
    initThread.Start();
}

public void InitializationThread()
{
    outputMessage("Initializing...");
    //DO INITIALIZATION
    outputMessage("Initialization Complete");
}

私はいくつかの記事を読みましたが、BackgroundWorker長いタスクを実行するためにスレッドを作成しなくてもアプリケーションの応答性を維持できるようにする方法を読みましたが、実装しようとして成功したことはありません。これを使用してBackgroundWorker


:私はこのチュートリアル便利な、それはいくつかの簡潔な例を持っていelegantcode.com/2009/07/03/...
GrandMasterFlush

そのリンクをクリックするとプライバシーエラーが発生します。
LittleBirdy

回答:


319
  1. を使用して追加
using System.ComponentModel;
  1. バックグラウンドワーカーの宣言:
private readonly BackgroundWorker worker = new BackgroundWorker();
  1. イベントを購読:
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
  1. 2つのメソッドを実装します。
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
  // run all background tasks here
}

private void worker_RunWorkerCompleted(object sender, 
                                           RunWorkerCompletedEventArgs e)
{
  //update ui once worker complete his work
}
  1. 必要なときにいつでもワーカーを非同期で実行します。
worker.RunWorkerAsync();
  1. 進捗状況を追跡します(オプションですが、多くの場合便利です)

    a)ProgressChangedイベントに登録して使用ReportProgress(Int32)するDoWork

    b)セットworker.WorkerReportsProgress = true;(@zagyへのクレジット)


これらのメソッドでDataContextにアクセスする方法はありますか?
susieloo_

36

Taskバックグラウンドワーカーの代わりに使用することも検討したい場合があります。

これを行う最も簡単な方法は、あなたの例ですTask.Run(InitializationThread);

バックグラウンドワーカーの代わりにタスクを使用することには、いくつかの利点があります。たとえば、.net 4.5の新しいasync / await機能はTaskスレッド化に使用します。https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskに関するドキュメントはこちらですTask


11
このスレッドを発掘して申し訳ありませんが、.net 4.0と4.5には、より使いやすいクールなものが追加されていますBackgroundWorker。それに人々を導くことを期待しています。
オーウェンジョンソン

1
今、この答えは、超古いであることを、チェックアウトするasyncawait。これらは、タスクをより読みやすい方法で使用するための言語統合された方法です。
オーウェンジョンソン

14
using System;  
using System.ComponentModel;   
using System.Threading;    
namespace BackGroundWorkerExample  
{   
    class Program  
    {  
        private static BackgroundWorker backgroundWorker;  

        static void Main(string[] args)  
        {  
            backgroundWorker = new BackgroundWorker  
            {  
                WorkerReportsProgress = true,  
                WorkerSupportsCancellation = true  
            };  

            backgroundWorker.DoWork += backgroundWorker_DoWork;  
            //For the display of operation progress to UI.    
            backgroundWorker.ProgressChanged += backgroundWorker_ProgressChanged;  
            //After the completation of operation.    
            backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;  
            backgroundWorker.RunWorkerAsync("Press Enter in the next 5 seconds to Cancel operation:");  

            Console.ReadLine();  

            if (backgroundWorker.IsBusy)  
            { 
                backgroundWorker.CancelAsync();  
                Console.ReadLine();  
            }  
        }  

        static void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)  
        {  
            for (int i = 0; i < 200; i++)  
            {  
                if (backgroundWorker.CancellationPending)  
                {  
                    e.Cancel = true;  
                    return;  
                }  

                backgroundWorker.ReportProgress(i);  
                Thread.Sleep(1000);  
                e.Result = 1000;  
            }  
        }  

        static void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)  
        {  
            Console.WriteLine("Completed" + e.ProgressPercentage + "%");  
        }  

        static void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)  
        {  

            if (e.Cancelled)  
            {  
                Console.WriteLine("Operation Cancelled");  
            }  
            else if (e.Error != null)  
            {  
                Console.WriteLine("Error in Process :" + e.Error);  
            }  
            else  
            {  
                Console.WriteLine("Operation Completed :" + e.Result);  
            }  
        }  
    }  
} 

また、以下のリンクを参照して、概念を理解してください。 Background

http://www.c-sharpcorner.com/UploadFile/1c8574/threads-in-wpf/


3

私はこれ(WPFマルチスレッド化:BackgroundWorkerの使用とUIへの進行状況の報告リンク)に、@ Andrewの回答から欠落している残りの詳細が含まれていることがわかりました。

私が非常に便利だと思ったのは、ワーカースレッドがMainWindowのコントロールに(それ自体のメソッドで)アクセスできないことですが、メインウィンドウのイベントハンドラー内でデリゲートを使用すると、可能でした。

worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
    pd.Close();
    // Get a result from the asynchronous worker
    T t = (t)args.Result
    this.ExampleControl.Text = t.BlaBla;
};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.