BackgroundWorker从外部类报告进度?

时间:2012-05-22 10:37:20

标签: c# .net winforms backgroundworker

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

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

然后我新创建的Class包含所有worker方法,并将进度推送到主窗体。

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调用?< / p>

3 个答案:

答案 0 :(得分:9)

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 :(得分:5)

sender回调中的DoWork对象是调用此回调的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);
}

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

答案 2 :(得分:0)

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

这是一个可以帮助您在项目中开始使用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));
                }
            }
        }

    }