วิธีใช้ WPF Background Worker


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. ใช้สองวิธี:
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. เรียกใช้งานคนงาน async เมื่อใดก็ตามที่คุณต้องการ
worker.RunWorkerAsync();
  1. ติดตามความคืบหน้า (ตัวเลือก แต่มักจะมีประโยชน์)

    a) สมัครสมาชิกProgressChangedกิจกรรมและใช้ReportProgress(Int32)ในDoWork

    b) ตั้งworker.WorkerReportsProgress = true;(เครดิตเป็น @zagy)


มีวิธีการเข้าถึง DataContext ในวิธีการเหล่านั้นหรือไม่
susieloo_

36

คุณอาจต้องการใช้Taskแทนผู้ทำงานเบื้องหลัง

Task.Run(InitializationThread);วิธีที่ง่ายที่สุดที่จะทำนี้ในตัวอย่างของคุณคือ

มีประโยชน์หลายประการในการใช้งานแทนที่จะเป็นพนักงานพื้นหลัง ตัวอย่างเช่นคุณลักษณะ async / await ใหม่ใน. net 4.5 ใช้Taskสำหรับเธรด นี่คือเอกสารเกี่ยวกับTask https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task


11
ขออภัยที่พบหัวข้อนี้ แต่สุทธิ 4.0 และ 4.5 BackgroundWorkerเพิ่มบางสิ่งที่เย็นที่เป็นวิธีที่ง่ายต่อการใช้งานมากกว่า หวังที่จะคัดท้ายผู้คนไป
โอเว่นจอห์นสัน

1
ตอนนี้คำตอบนี้เป็นซุปเปอร์เก่าตรวจสอบและasync awaitภาษาเหล่านี้เป็นวิธีบูรณาการในการใช้งานในวิธีที่อ่านได้มากขึ้น
โอเว่นจอห์นสัน

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 Multithreading: การใช้ 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.