WPF多线程进度更新

时间:2015-05-15 11:51:22

标签: c# wpf multithreading

我需要向用户显示某种形式的反馈,而在后台进行一个小程序(7-10秒)。

过去我在Windows窗体中使用单独的线程和BackgroundWorkers没有任何问题,但在WPF中证明它很难。

在这方面,我已经阅读了很多文章,以及我应该如何在WPF中使用调度程序来启动新线程等。但是,当我尝试使用BackgroundWorker来显示等待图像反馈的形式时,它只是保持不变。

我不相信这很重要,但它使用的是来自FirstFloor(https://github.com/firstfloorsoftware/mui)的mui。

我试图使用内置的ProgressRing功能(在同一个线程中运行时没有任何问题,并且后台没有其他主要任务在运行。

添加BackgroundWorker会因对象的跨线程访问而带来异常,即使许多博客都指出WPF中的BackgroundWorks具有跨线程感知功能且可以安全运行。

以下是产生我需要的最接近的代码。

    private async void MyTaskProcess()
    {

        await Dispatcher.BeginInvoke(DispatcherPriority.Send, new ThreadStart(() =>
        {
            try
            {
                //Update the waiting ring image
                ProgressRing.IsActive = true;
            }
            catch
            {
                ProgressRing.IsActive = false;
                MessageBox.Show("Exception Thrown");
            }
        }));


        await Dispatcher.BeginInvoke(DispatcherPriority.Background, new ThreadStart(() =>
        {
            try
            {        
                //Run the main MS Excel export function
                Export2Excel();
                ProgressRing.IsActive = false;
            }
            catch
            {
                MessageBox.Show("Exception Thrown");
            }
        }));

    }

感谢任何反馈。

3 个答案:

答案 0 :(得分:1)

在现代WPF应用程序中执行此操作的方法是启动一个新的Task,您可以在其中执行此操作;这将在线程池线程上执行工作:

Task.Factory.StartNew(this.DoWork)

现在在DoWork中,当porgress计数发生变化时,您将InvokeAsync的进度报告回主线程:

void DoWork()
{
    foreach(var item in this.WorkItems)
    {
        // Do something

        // Report Progress
        ++progress
        Application.Current.Dispatcher.InvokeAsync(() => this.Progress = progress);
    }
}

答案 1 :(得分:1)

  

添加BackgroundWorker会因对象的跨线程访问而带来异常,即使许多博客都指出WPF中的BackgroundWorks具有跨线程感知功能且可以安全运行。

只需在UI线程上创建并启动BGW,

BackgroundWorker可以正常使用WPF,。 (作为旁注,BGW对Windows Forms具有相同的限制)。正如其他评论者所指出的那样,使用BGW进行进度更新的正确方法是使用ReportProgress,而不是Dispatcher

但是,我建议您使用较新的Task.RunIProgress<T>进行更新。我有blog post比较/对比旧的BGW进度更新与基于IProgress<T>的新进度更新。

很难说出您的代码应该是什么样子,因为您发布的代码在后台线程上实际上并没有运行任何内容。特别是,如果必须在UI线程上运行Export2Excel,并且您的所有工作都在进行,那么使用BGW或Task.Run毫无意义,因为无论如何也无法在后台线程上运行。

答案 2 :(得分:0)

你去,到我写的下面的链接,仔细阅读。我希望你能明确地解决你的问题:

Threads in WPF