是否可以从2个后台工作人员更新UI

时间:2013-12-31 14:16:42

标签: c# wpf multithreading backgroundworker

我正在使用C#编写WPF应用程序,我想实现第二个后台工作器对象。我已经有1个以我想要的方式工作。

第一个后台工作人员根据某些操作更新进度条。 我希望第二个更新显示倒数计时器的文本块。

首先,这可能吗? 目前,当计时器倒计时并达到零时,当另一个线程尝试访问进度条时,它会出错。

  

调用线程无法访问此对象,因为另一个线程拥有它。

以下是我的后台工作人员的代码: 在主窗口方法中,我初始化它们。

        // Add the background worker events
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.WorkerReportsProgress = true;

        worker_timer.DoWork += worker_TrackTime;
        worker_timer.RunWorkerCompleted += worker_TimeCompleted;
        worker_timer.ProgressChanged += worker_timerProgressChanged;
        worker_timer.WorkerReportsProgress = true;

以下是线程方法:

private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        // Run all background tasks here
        copyEverything(sourceFolder, targetFolder);
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // Update UI once worker complete his work
        // Update the progress bar and progress percent text to the max value it can be
        copy_progressbar.Value = copy_progressbar.Maximum;
        copy_textblock.Text = copy_progressbar.Maximum + "%";

        worker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        worker.DoWork -= new DoWorkEventHandler(worker_DoWork);
    }

    void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        // Update something here
        copy_progressbar.Value = e.ProgressPercentage;
        copy_textblock.Text = e.ProgressPercentage + "%";

        // Check if the progressbar has reached its maximum value, if so set the value to its max
        if (copy_progressbar.Value >= copy_progressbar.Maximum)
        {
            copy_progressbar.Value = copy_progressbar.Maximum;
            copy_textblock.Text = copy_progressbar.Maximum + "%";
        }
    }

    private void worker_TimeCompleted(object sender, RunWorkerCompletedEventArgs e)
    {

    }

    private void worker_TrackTime(object sender, DoWorkEventArgs e)
    {
        while (true)
        {
            Thread.Sleep(1000);
            elapsedTS = elapsedTS.Add(new TimeSpan(0, 0, 1));
            try
            {
                worker_timer.ReportProgress(1);
            }
            catch
            {
            }

            if (elapsedTS >= schedule.TS)
            {
                copyEverythingAsync(sourceFolder, targetFolder);
                schedule.updateSchedule(DateTime.Now, false);
                schedule.checkSchedule();
                checkScheduleTime();

                elapsedTS = TimeSpan.Zero;
            }
        }
    }

    private void worker_timerProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        time_left_textblock.Text = "" + schedule.TS.Subtract(elapsedTS).ToString(@"dd\.hh\:mm\:ss");
        //time_left_textblock.Text = "" + schedule.TS.Subtract(elapsedTS).ToString();
    }

跟踪计时器的线程没有完整的方法,因为我希望它能够连续运行。

如果需要,我可以提供更多信息。

1 个答案:

答案 0 :(得分:1)

您需要使用UI线程更新UI。

   private void worker_timerProgressChanged(object sender, ProgressChangedEventArgs e)
    {
       Dispatcher.Invoke(() => 
       {
          time_left_textblock.Text = "" + schedule.TS.Subtract(elapsedTS).ToString(@"dd\.hh\:mm\:ss");
       });
    }