通过函数参数调用BackgroundWorker.ReportProgress()

时间:2012-01-15 08:17:29

标签: c# .net multithreading backgroundworker

我是一个像其他人一样懒散的开发人员:)为什么我尝试编写一个静态方法来使用BackgroundWorker。这种方法就是吹嘘:

public static void RunInThread( DoWorkEventHandler method
                                    ,ProgressChangedEventHandler progressHandler
                                    ,RunWorkerCompletedEventHandler completed)
    {
        var bkw = new BackgroundWorker();
        bkw.DoWork += method;
        bkw.ProgressChanged += progressHandler;
        bkw.RunWorkerCompleted += completed;
        bkw.WorkerReportsProgress = true;
        bkw.RunWorkerAsync();
    }

但是我有一个使用BackgroundWorker.ReportProgress方法的问题。 这里有谁可以帮助我吗? tnx

2 个答案:

答案 0 :(得分:0)

如果不是从void返回RunInThread而是返回BackgroundWorker类(bkw)的对象,然后在DoWork中使用该实例调用{{1} }}

答案 1 :(得分:0)

虽然Haris的解决方案是可接受的“快速解决方案”,但您的静态方法存在一个主要的设计缺陷;作为BackgroundWorkerComponent类实现IDisposable,因此应该在其生命的最后处置。

重新创建模式的最佳方法是在另一个线程上手动调用您的工作函数。唯一的缺点是,当您更新进度时,必须调用Dispatcher.Invoke才能与UI线程上的任何内容进行交互。以下是您如何做到这一点的示例。

using System.Threading;

public static void RunInThread<TProgress>(
    Action<Action<TProgress>> worker,
    Action<TProgress> updateProgress,
    Action workerCompleted)
{
    Thread workerThread = new Thread(() =>
    {
        worker(updateProgress);
        workerCompleted();
    });

    workerThread.Start();
}

因为它是一种通用方法,您可以使用它来报告您喜欢的任何类型的进度。以下是您可以调用它的示例:

RunInThread<double>(
    updateProgress =>
    {
        Thread.Sleep(500);
        updateProgress(0.5);

        Thread.Sleep(500);
        updateProgress(1);
    },
    progress =>
    {
        this.Dispatcher.Invoke(() =>
        {
            progressLabel.Text = progress.ToString();
        });
    },
    () =>
    {
        this.Dispatcher.Invoke(() =>
        {
            progressLabel.Text = "Finished!";
        });
    }
);

您还可以非常轻松地自定义此方法,以创建在使用单个参数或返回值时更轻松的重载。

public static void RunInThread<TProgress, TParameter>(
    Action<Action<TProgress>, TParameter> worker,
    Action<TProgress> updateProgress,
    Action workerCompleted,
    TParameter parameter)
{
    Thread workerThread = new Thread(() =>
    {
        worker(updateProgress, parameter);
        workerCompleted();
    });

    workerThread.Start();
}

public static void RunInThread<TProgress, TResult>(
    Func<Action<TProgress>, TResult> worker,
    Action<TProgress> updateProgress,
    Action<TResult> workerCompleted)
{
    Thread workerThread = new Thread(() =>
    {
        TResult result = worker(updateProgress);
        workerCompleted(result);
    });

    workerThread.Start();
}

public static void RunInThread<TProgress, TParameter, TResult>(
    Func<Action<TProgress>, TParameter, TResult> worker,
    Action<TProgress> updateProgress,
    Action<TResult> workerCompleted,
    TParameter parameter)
{
    Thread workerThread = new Thread(() =>
    {
        TResult result = worker(updateProgress, parameter);
        workerCompleted(result);
    });

    workerThread.Start();
}

我还建议您添加一些错误处理代码,以防万一在您的工作职能中出现任何问题,但我会将此练习留给您。