ความช่วยเหลือเกี่ยวกับ C#.NET BackgroundWorker

ฉันกำลังลองทดสอบง่ายๆ เพื่อใช้ BackgroundWorker ในแอปของฉัน ฉันเห็นว่าผู้ปฏิบัติงานเบื้องหลังกำลังดำเนินการอยู่ แต่ด้วยเหตุผลบางประการ เธรดหลักจึงได้รับการแจ้งเตือนความคืบหน้า

ฉันคงขาดอะไรบางอย่างที่ธรรมดามากที่นี่ ใครช่วยชี้ให้เห็นว่าฉันผิดตรงไหน?

นี่คือรหัสสำหรับการทดสอบอย่างง่ายของฉัน:

namespace TestBackgroundWorker
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            progressBar1.Maximum = 100;
            progressBar1.Minimum = 0;
            progressBar1.Value = 0;
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.RunWorkerAsync();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            int progress = 0;
            while (true)
            {
                Thread.Sleep(1000);
                System.Diagnostics.Debug.WriteLine("worker: progress={0}", progress);
                worker.ReportProgress(progress);
                progress = (progress + 10) % 100;
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("main: process progress={0}", e.ProgressPercentage);
            progressBar1.Value = e.ProgressPercentage;
        }
    }
}

และนี่คือสิ่งที่ฉันได้รับจากหน้าต่างเอาท์พุต มันแสดงให้เห็นว่าคนงานกำลังตื่นขึ้นมาและกำลังทำสิ่งนั้นอยู่ แต่เธรดหลักไม่ได้รับการอัปเดตความคืบหน้าใดๆ:

worker: progress=0
worker: progress=10
worker: progress=20
worker: progress=30
worker: progress=40
worker: progress=50
worker: progress=60
worker: progress=70
worker: progress=80
worker: progress=90
worker: progress=0
worker: progress=10
worker: progress=20
worker: progress=30
worker: progress=40
worker: progress=50
worker: progress=60
worker: progress=70
worker: progress=80
The thread '<No Name>' (0x1e84) has exited with code 0 (0x0).
worker: progress=90
worker: progress=0
worker: progress=10
worker: progress=20
worker: progress=30
worker: progress=40
worker: progress=50
worker: progress=60
worker: progress=70
worker: progress=80
worker: progress=90
worker: progress=0
worker: progress=10
worker: progress=20
worker: progress=30
worker: progress=40
worker: progress=50
worker: progress=60
worker: progress=70
worker: progress=80
worker: progress=90
worker: progress=0
worker: progress=10
worker: progress=20
worker: progress=30
worker: progress=40
worker: progress=50
The thread 'vshost.RunParkingWindow' (0x2760) has exited with code 0 (0x0).
The thread '<No Name>' (0x29c8) has exited with code 0 (0x0).
The program '[3528] TestBackgroundWorker.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).

person Denis    schedule 22.08.2011    source แหล่งที่มา


คำตอบ (3)


นี่อาจฟังดูเป็นคำถามงี่เง่า แต่คุณแน่ใจหรือว่าฟังก์ชันการโทรกลับเชื่อมโยงกับเหตุการณ์ ProgressChanged

รหัสต่อไปนี้:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            new Program().Run();
        }

        void Run()
        {
            var worker = new BackgroundWorker { WorkerReportsProgress = true };

            worker.ProgressChanged += WorkerOnProgressChanged;
            worker.DoWork += WorkerOnDoWork;
            worker.RunWorkerAsync();

            Console.ReadKey();
        }

        private void WorkerOnDoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; ; i++)
            {
                Debug.WriteLine("[Thread #{0,2} (worker)] Progress:{1}", Thread.CurrentThread.ManagedThreadId, i);
                (sender as BackgroundWorker).ReportProgress(i);
                Thread.Sleep(1000);
            }
        }

        private void WorkerOnProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Debug.WriteLine("[Thread #{0,2} (main  )] Progress:{1}", Thread.CurrentThread.ManagedThreadId, e.ProgressPercentage);
        }
    }
}

จะส่งออกดังต่อไปนี้:

[Thread # 7 (worker)] Progress:0
[Thread #11 (main  )] Progress:0
[Thread # 7 (worker)] Progress:1
[Thread #11 (main  )] Progress:1
[Thread # 7 (worker)] Progress:2
[Thread #11 (main  )] Progress:2
[Thread # 7 (worker)] Progress:3
[Thread #11 (main  )] Progress:3
[Thread # 7 (worker)] Progress:4
[Thread #11 (main  )] Progress:4
[Thread # 7 (worker)] Progress:5
[Thread #11 (main  )] Progress:5
[Thread # 7 (worker)] Progress:6
[Thread #11 (main  )] Progress:6
[Thread # 7 (worker)] Progress:7
[Thread #11 (main  )] Progress:7
[Thread # 7 (worker)] Progress:8
[Thread #12 (main  )] Progress:8
person edvaldig    schedule 22.08.2011
comment
อย่างที่ฉันพูดไป ฉันคิดว่ามันจะเป็นสิ่งที่พื้นฐานมากและเป็นเช่นนั้นจริงๆ คุณปังกับเงิน ขอบคุณ! - person Denis; 22.08.2011

การสมัครสมาชิกกิจกรรม ProgressChanged หายไปในรหัสของคุณ:

backgroundWorker1.ProgressChanged += พื้นหลังคนทำงาน1_ProgressChanged;

person Alex F    schedule 22.08.2011
comment
น่าสนใจ. ฉันกำลังติดตามตัวอย่างแรกในเอกสาร MSDN (ดู //msdn.microsoft.com/en-us/library/) และในตัวอย่างแรก พวกเขาไม่ได้กล่าวถึงสิ่งใดเกี่ยวกับการสมัครตัวจัดการ ProgressChanged อย่างไรก็ตาม เมื่อคุณพูดถึงมันแล้ว ผมเห็นว่าตัวอย่างที่สอง (ตัวอย่าง Fibonacci) เป็นเช่นนั้น - person Denis; 22.08.2011

คุณพลาดการมอบหมาย EventHandler ที่ไหนสักแห่งหรือไม่? ฉันไม่เห็นที่นี่

ฉันพนันได้เลยว่าคุณไม่มีโค้ดของนักออกแบบที่มีลักษณะดังต่อไปนี้:

this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);

นี่เป็นปัญหาของการใช้โค้ดที่สร้างขึ้นอัตโนมัติจากการลากและวาง GUI เมื่อถูกงูกัด ผู้คนไม่รู้ว่าจะแก้ไขอย่างไร

ลองลบ BackgroundWorker แล้วเริ่มต้นใหม่

person rstackhouse    schedule 22.08.2011
comment
ใช่. การผูกตัวจัดการเหตุการณ์คือสิ่งเดียวที่ฉันขาดหายไป ขอบคุณ. - person Denis; 22.08.2011