【问题标题】:BackgroundWorker report progress from external Class?BackgroundWorker 从外部类报告进度?
【发布时间】:2015-11-08 07:36:57
【问题描述】:

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

在工作方法中是 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 调用?

【问题讨论】:

    标签: c# .net winforms backgroundworker


    【解决方案1】:

    在您的 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 });
                }
            }
        }
    }
    

    【讨论】:

    • 正是我所追求的,+1!
    • 当然,这可以稍微优化和扩展,但你会明白基本的想法。 =)
    【解决方案2】:

    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)
        {
        // ...
        }
    }
    


    或者您将BackgroundWorkerinstance 作为类属性设置为XMLandRar

    public class XMLandRar
    {
        protected BackgroundWorker mWorker;
    
        public XMLandRar(BackgroundWorker worker) {
            mWorker = BackgroundWorker;
        }
    
    
        public void RarFiles(List repSelected)
        {
            // Do something with {mWorker}
        }
    }
    

    如 cmets 中所述,使用 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);
    }
    

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

    【讨论】:

    • @HenkHolterman - 你能详细说明一下答案吗?你的意思是要成为一个适当的可重用类,那么 RarFiles 必须不知道 GUI,因为这会使它特定于那种情况?
    • @HenkHolterman 所以我真正需要做的是分离出 GUI 修改代码,把它放在主窗体中,并且在任何窗体/CLI/ 的类中只有一个通用的报告更新事件/回调页面可以用自己的方式监听和处理吗?
    • 感谢@GodLesZ - 不错的解决方案,我相信我会使用零碎完成等+1。
    【解决方案3】:

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

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

    只要修改这个方法——

        public void RarFiles(List<string> repSelected)
    

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

         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));
                    }
                }
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多