C# 编写报告进度的方法

C# 编写报告进度的方法,c#,multithreading,progress-bar,progress,C#,Multithreading,Progress Bar,Progress,我正在编写一个在库中执行特定操作的类。但是这个操作很繁琐,我希望能够找出该类中方法的进度,以便在WinForms应用程序中使用它来报告进度 我计划在我的WinForms应用程序的另一个线程上运行我的类,我希望该类与WinForms应用程序的关注点分开,我不想将它绑定到任何特定的东西,除了它的功能 在库类中实现进度报告机制的最佳方法是什么 在类中添加一个进度变量,并在WinForms应用程序中添加一个事件侦听器,这是一个好主意吗?如果是,我该怎么做 Edit:我以前使用过BackgroundWor

我正在编写一个在库中执行特定操作的类。但是这个操作很繁琐,我希望能够找出该类中方法的进度,以便在WinForms应用程序中使用它来报告进度

我计划在我的WinForms应用程序的另一个线程上运行我的类,我希望该类与WinForms应用程序的关注点分开,我不想将它绑定到任何特定的东西,除了它的功能

在库类中实现进度报告机制的最佳方法是什么

在类中添加一个进度变量,并在WinForms应用程序中添加一个事件侦听器,这是一个好主意吗?如果是,我该怎么做


Edit:我以前使用过
BackgroundWorker
类,但我的问题是我不希望我的库类涉及任何多线程操作。因此,我不想在library类中调用
ReportProgress
,我希望(可能)在类中有一个包含当前进度的变量,我希望UI线程以某种方式“订阅”它。我不知道这是否是一个好的设计方法。

在这里,你可以用两种不同的方法,我将在下面发布这两个选项,以帮助你找到正确的方向

您应该在另一个线程上执行此操作,然后从该线程更新UI线程。通过在UI线程上执行此工作,您正在阻止进一步的处理

如果您无法将此代码移动到UI线程,那么您可以随时调用,但我建议您首先探索以下选项:

第二种选择是,您可以这样做:

    private void StartProcessing()
    {
        System.Threading.Thread procThread = new System.Threading.Thread(this.Process);

        procThread.Start();
    }

    private void Process() // this is the actual method of the thread
    {
        foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
        {
            // Do processing
            // Show progress bar
            // Update Label on Form, "f.Name is done processing, now processing..."
            UpdateStatus("Processing " + f.Name + "...");                
        }
    }
您需要从一个线程到另一个线程获取数据。这可以通过两种方式实现

首先,您的“后台”线程可以更新某种“CurrentStatus”字符串变量,它会随着时间的推移而改变。然后,您可以在表单上放置一个计时器,该计时器将获取CurrentStatus变量并用它更新标签

其次,您可以使用label控件的InvokeRequired属性通过委托简单地从后台线程调用操作到UI线程。比如说

private delegate void UpdateStatusDelegate(string status);
private void UpdateStatus(string status)
{
    if (this.label1.InvokeRequired)
    {
        this.Invoke(new UpdateStatusDelegate(this.UpdateStatus), new object[] { status });
        return;
    }

    this.label1.Text = status;
}
您可以从任何线程(UI或后台)调用UpdateStatus()方法,它将检测是否需要调用主UI线程上的操作(如果需要,则执行)

编辑:要实际设置线程,您可以这样做:

    private void StartProcessing()
    {
        System.Threading.Thread procThread = new System.Threading.Thread(this.Process);

        procThread.Start();
    }

    private void Process() // this is the actual method of the thread
    {
        foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
        {
            // Do processing
            // Show progress bar
            // Update Label on Form, "f.Name is done processing, now processing..."
            UpdateStatus("Processing " + f.Name + "...");                
        }
    }
然后,当用户单击“GO”按钮时,您只需调用StartProcessing()。

查看该类。它支持跨线程自动封送以进行进度报告,并且它有一个非常简单的事件模型来支持这种支持

编辑:鉴于您对直接使用BackgroundWorker的立场,您可以做的是创建一个简单的包装器:

// Error checking elided for expository purposes.
public interface IProgressReporter 
{
    void ReportProgress(int progress, object status);
}

public class BackgroundWorkerProgressReporter : IProgressReporter
{
    private BackgroundWorker _worker;
    public BackgroundWorkerProgressReporter(BackgroundWorker worker)
    {
        _worker = worker;
    }

    public void ReportProgress(int progress, object status)
    {
        _worker.ReportProgress(progress, status);
    }
}

然后,更改要报告进度的类的构造函数(或添加属性)以接受IProgressReporter。这是一种依赖注入形式,应该有意义地允许您的对象报告进度,同时避免对线程库的特定依赖。

有许多不同的方法来实现这一点,但是您现有的代码是什么样子的。。?如果你能提供到目前为止你已经尝试过的东西,那会有帮助的。我现在没有太多的代码。在写这门课之前,我想先弄清楚如何进行。如果你能给我指出一些解决这个问题的众所周知的方法,我将不胜感激。