【发布时间】:2014-01-01 00:01:33
【问题描述】:
我正在使用 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();
}
跟踪计时器的线程没有完成的方法,因为我希望它继续运行。
如果需要,我可以提供更多信息。
【问题讨论】:
-
在 ProgressChangedEventArgs e 中传递 elapsedTS。不要尝试直接访问它。
-
始终检查 Completed 事件中的错误。
-
这个问题与后台worker的数量无关。您的标题暗示出现此问题是因为这是第二部作品。但事实上,问题在于,您正在尝试更新 UI - 如果您只有 1 个后台工作人员正在执行此操作,您会看到相同的错误。正如 Mayank 指出的那样,您需要分派回 UI 线程以更新 UI。
-
@IanGriffiths BGW 的整个点 是代表您为除
DoWork事件之外的所有事件处理程序编组到UI 线程。所以不,您不需要“总是需要手动分派回 UI 线程”。 -
您不应该在一段时间后使用 BGW 来运行某些代码。您应该为此使用
Timer。由于这是专为您正在尝试做的工作而设计的工具,您会发现它更容易使用。至于您看到的错误,您没有显示足够的代码来复制问题。
标签: c# wpf multithreading backgroundworker