后台工作线程报告来自外部类的进度

本文关键字:外部 工作 线程 报告 后台 | 更新日期: 2023-09-27 18:35:01

我有一个工作解决方案,可以将进度和文本报告到进度条和应用程序主窗体上的标签。我现在已经将我的 worker 方法移动到一个类中,以便它们可以跨多个表单等访问。

在 worker 方法中BW.ReportProgress()语句,这些语句将进度和文本推送回主窗体中的 BackgroundWorker 。

为了给出更好的主意,这里是文件布局:

MainScreen.cs

List repSelected = new List();
XMLandRar xXMLandRar = new XMLandRar();
private void Rarbtn_Click(object sender, EventArgs e)
        {
            GetReps();
            //Run worker
            if (!CreateRarBW.IsBusy)
            {
                CreateRarBW.RunWorkerAsync();
            }
        }
//Worker
private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
{
    xXMLandRar.RarFiles(repSelected);
}
//Progress reporting
private void CreateRarBW_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progBar.Value = e.ProgressPercentage;
    Statuslbl.Text = e.UserState.ToString();
}

然后是我新创建的类,它包含所有工作线程方法,并将进度推送到主窗体。

XMLandRar.cs

public class XMLandRar
{
    public void RarFiles(List repSelected)
    {
        int step = 100 / repSelected.Count();
        int i = 0;
        //Iterate through list and run rar for each
        foreach (string rep in repSelected)
        {
            CreateRarBW.ReportProgress(i, "Raring files for " + rep);
            DirectoryExists(rep);
            ProcessRunner(rep);
            i += step;
            CreateRarBW.ReportProgress(i, "Raring files for " + rep);
        }
    }
}

我遇到的问题是,在XMLandRar类中,CreateRarBW 无法识别(显然( - 如何在应用程序的主屏幕中对 BW 进行ReportProgress调用?

后台工作线程报告来自外部类的进度

XMLandRar类中创建一个可以订阅的事件。

这样,XMLandRar类就不需要知道或关心 UI 或进度条,它只关心在有人愿意听时发送消息。而且也可以有多个订阅者(假设您是否要向后台工作者和日志报告,也许(

例:

private void Rarbtn_Click(object sender, EventArgs e)
{
    GetReps();
    //Run worker
    if (!CreateRarBW.IsBusy)
    {
        // This should be done once, maybe in the contructor. Bind to new event.
        xXMLandRar.ReportProgress += new EventHandler<XMLandRar.ProgressArgs>(xXMLandRar_ReportProgress);
        CreateRarBW.RunWorkerAsync();
    }
}
protected void xXMLandRar_ReportProgress(object sender, XMLandRar.ProgressArgs e)
{
    // Call the UI backgroundworker
    CreateRarBW.ReportProgress(e.Percentage, e.Message);
}
public class XMLandRar
{
    // Event handler to bind to for reporting progress
    public EventHandler<ProgressArgs> ReportProgress;
    // Eventargs to contain information to send to the subscriber
    public class ProgressArgs : EventArgs
    {
        public int Percentage { get; set; }
        public string Message { get; set; }
    }
    public void RarFiles(List repSelected)
    {
        int step = 100 / repSelected.Count();
        int i = 0;
        //Iterate through list and run rar for each
        foreach (string rep in repSelected)
        {
            // Report progress if somebody is listening (subscribed)
            if (ReportProgress != null)
            {
                ReportProgress(this, new ProgressArgs { Percentage = i, Message = "Raring files for " + rep });
            }
            DirectoryExists(rep);
            ProcessRunner(rep);
            i += step;
            // Report progress if somebody is listening (subscribed)
            if (ReportProgress != null)
            {
                ReportProgress(this, new ProgressArgs { Percentage = i, Message = "Raring files for " + rep });
            }
        }
    }
}
DoWork

调中的sender对象是调用此回调的BackgroundWorker实例。

这样就可以使用该实例并将其添加到新的XMLandRar类中。

private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
{
    var worker = sender as BackgroundWorker.
    xXMLandRar.RarFiles(repSelected, worker);
}

XMLandRar.cs

public class XMLandRar
{
    public void RarFiles(List repSelected, BackgroundWorker worker)
    {
    // ...
    }
}


或者BackgroundWorker实例设置为XMLandRar的类属性。

public class XMLandRar
{
    protected BackgroundWorker mWorker;
    public XMLandRar(BackgroundWorker worker) {
        mWorker = BackgroundWorker;
    }

    public void RarFiles(List repSelected)
    {
        // Do something with {mWorker}
    }
}

或者如注释中所述,使用 XMLandRar 类中的事件。

XMLandRar.cs

public class XmlandRarCompletedEventArgs : EventArgs
{
    public readonly bool Finished;
    public readonly bool Canceled;
    public XmlandRarCompletedEventArgs(bool finished)
    {
        Finished = finished;
        Canceled = !finished;
    }    
}public class OnXmlandRarUpdateEventArgs : EventArgs
{
    public readonly int Percentage;
    public readonly string Message;
    public XmlandRarCompletedEventArgs(int perc) :
        this(perc, "") {
    }   
    public XmlandRarCompletedEventArgs(int perc, string message)
    {
        Percentage = perc;
        Message = message;
    }    
}
public delegate void OnXmlandRarDoWorkHandler(object o);
public delegate void OnXmlandRarUpdateHandler(object o, OnXmlandRarUpdateEventArgs args);
public delegate void OnXmlandRarCompleteHandler(object o, XmlandRarCompletedEventArgs args);
public class XMLandRar
{
    public event OnXmlandRarDoWorkHandler OnDoWork;
    public event OnXmlandRarUpdateHandler OnUpdate;
    public event OnXmlandRarCompletedHandler OnComplete;
    public void RarFiles(List repSelected)
    {
        TriggerDoWork();
        int step = 100 / repSelected.Count();
        int i = 0;
        //Iterate through list and run rar for each
        foreach (string rep in repSelected)
        {
            TriggerUpdate(i, "Raring files for " + rep);
            DirectoryExists(rep);
            ProcessRunner(rep);
            i += step;
            TriggerUpdate(i, "Raring files for " + rep);
        }
        TriggerComplete(true);
    }

    private void TriggerDoWork() 
    {
        if (OnDoWork != null) {
            OnDoWork(this);
        }
    }
    private void TriggerUpdate(perc) {
    }
        if (OnUpdate != null) {
            OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc));
        }
    private void TriggerUpdate(perc, string message) 
    {
        if (OnUpdate != null) {
            OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc, message));
        }
    }
    private void TriggerComplete(bool finished)
    {
        if (OnComplete != null) {
            OnComplete(this, new XmlandRarCompletedEventArgs(finished));
        }
    }
}

用法:

private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
{
    var worker = sender as BackgroundWorker;
    // Attach events to class
    xXMLandRar.OnDoWork += delegate(object o) {
        // ...
    };
    xXMLandRar.OnUpdate += delegate(object o, OnXmlandRarUpdateEventArgs args) {
        // ...
    };
    xXMLandRar.OnComplete += delegate(object o, XmlandRarCompletedEventArgs args) {
        // ...
    };
    xXMLandRar.RarFiles(repSelected, worker);
}

希望没有错别字,因为我在办公室。

我已经修复了提交的代码中的错误并清理了它......这是一个工作示例,它将帮助那些可能无法理解代码的人,因为它被破坏了......虽然我想说的是,清理和增强后代码的意图和功能非常好。

这是工作代码,可以让您开始在项目中使用 backGroundWorker 线程来满足您需要的任何需求。

只需修改此方法 -

    public void RarFiles(List<string> repSelected)

做你需要的任何工作。您还必须修改您计划使用的参数。即您可能需要一个数据表或一些自定义对象...您可以修改

     public class OnXmlandRarUpdateEventArgs : EventArgs

为了您的需要..这样当你收到回调时..你可以用对这些项目所做的更改来更新你的主UI表单。

可能需要做一些调整......但你明白我的意思。

这是表单代码..不要忘记在表单上创建一个按钮...

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    namespace ThreadSample
    {
        public partial class Form1 : Form
        {
            List<string> repSelected = new List<string>();
            XMLandRar xXMLandRar = new XMLandRar();
            BackgroundWorker CreateRarBW = new BackgroundWorker();
            public Form1()
            {
                InitializeComponent();
                repSelected = new List<string> { "asdf", "asdfsd", "h;ljj" };
                CreateRarBW.DoWork += new DoWorkEventHandler(CreateRarBW_DoWork);
            }
            private void Rarbtn_Click(object sender, EventArgs e)
            {
                //GetReps();
                //Run worker
                if (!CreateRarBW.IsBusy)
                {
                    // This should be done once, maybe in the contructor. Bind to new event.
                    xXMLandRar.ReportProgress += new EventHandler<XMLandRar.ProgressArgs>(xXMLandRar_ReportProgress);
                    CreateRarBW.RunWorkerAsync();
                }
            }
            protected void xXMLandRar_ReportProgress(object sender, XMLandRar.ProgressArgs e)
            {
                // Call the UI backgroundworker
                CreateRarBW.ReportProgress(e.Percentage, e.Message);
            }
            //private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
            //{
            //    var worker = sender as BackgroundWorker;
            //    xXMLandRar.RarFiles(repSelected, worker);
            //}

            private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
            {
                var worker = sender as BackgroundWorker;
                // Attach events to class
                xXMLandRar.OnDoWork += delegate(object o)
                {
                    // ...
                    MessageBox.Show("Hey ... Something is going on over there in the classLib .. " + o);
                };
                xXMLandRar.OnUpdate += delegate(object o, OnXmlandRarUpdateEventArgs args)
                {
                    // ...
                    //foreach (object oo in args)
                    {
                        MessageBox.Show("Hey ... Something is going on over there in the classLib .. Message is " + args.Message + " and Percentage is " + args.Percentage);
                    }
                };
                xXMLandRar.OnComplete += delegate(object o, XmlandRarCompletedEventArgs args)
                {
                    MessageBox.Show("Hey ... Something is going on over there in the classLib .. Canceled is " + args.Canceled + " and Finished is " + args.Finished);
                    // ...
                };
                xXMLandRar.RarFiles(repSelected);//, worker);
            }
        }
    }

这是类代码。您可以在当前项目中创建一个类...请记住,CreateRarBW 对象是一个 BackGroundWorker 实例...(上面未包含。

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Diagnostics;
    using System.Threading;
    namespace ThreadSample
    {
        public class XmlandRarCompletedEventArgs : EventArgs
        {
            public readonly bool Finished;
            public readonly bool Canceled;
            public XmlandRarCompletedEventArgs(bool finished)
            {
                Finished = finished;
                Canceled = !finished;
            }
        }
        public class OnXmlandRarUpdateEventArgs : EventArgs
        {
            public readonly int Percentage;
            public readonly string Message;

            public OnXmlandRarUpdateEventArgs(int perc) : this(perc, "")
            {
            }   
            public OnXmlandRarUpdateEventArgs(int perc, string message)
            {
                Percentage = perc;
                Message = message;
            }
        }
        public delegate void OnXmlandRarDoWorkHandler(object o);
        public delegate void OnXmlandRarUpdateHandler(object o, OnXmlandRarUpdateEventArgs args);
        public delegate void OnXmlandRarCompleteHandler(object o, XmlandRarCompletedEventArgs args);
        public class XMLandRar      // : BackgroundWorker
        {
            // Event handler to bind to for reporting progress
            public EventHandler<ProgressArgs> ReportProgress;
            // Eventargs to contain information to send to the subscriber
            public class ProgressArgs : EventArgs
            {
                public int Percentage { get; set; }
                public string Message { get; set; }
            }
            public event OnXmlandRarDoWorkHandler OnDoWork;
            public event OnXmlandRarUpdateHandler OnUpdate;
            public event OnXmlandRarCompleteHandler OnComplete;
            public void RarFiles(List<string> repSelected)
            {
                TriggerDoWork();
                int step = 100 / repSelected.Count();
                int i = 0;
                //Iterate through list and run rar for each
                foreach (string rep in repSelected)
                {
                    TriggerUpdate(i, "Raring files for " + rep);
                    //DirectoryExists(rep);
                    //ProcessRunner(rep);
                    i += step;
                    TriggerUpdate(i, "Raring files for " + rep);
                }
                TriggerComplete(true);
            }

            private void TriggerDoWork()
            {
                if (OnDoWork != null)
                {
                    OnDoWork(this);
                }
            }
            private void TriggerUpdate(int perc)
            {
                if (OnUpdate != null)
                {
                    OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc));
                }
            }
            private void TriggerUpdate(int perc, string message)
            {
                if (OnUpdate != null)
                {
                    OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc, message));
                }
            }
            private void TriggerComplete(bool finished)
            {
                if (OnComplete != null)
                {
                    OnComplete(this, new XmlandRarCompletedEventArgs(finished));
                }
            }
        }
    }