我正在学习使用BackgroundWorker类并创建了一个简单的程序来使用。
我整理了一个非常简单的应用程序。它有两个.xamls,一个是MainWindow,另一个是WorkersRunningUI。 MainWindow只有一个按钮,WorkersRunningUI有一个标签。然后是Worker.cs类,它包含所有BackgroundWorker逻辑。
我的目标: 当我单击MainWindow上的按钮时,我希望隐藏MainWindow并显示WorkersRunningUI。然后,这将启动一个BackgroundWorker,他将进行一些处理(增量 计数器),在计数器递增时更新WorkersRunningUI中的标签,一旦完成就隐藏WorkersRunningUI并再次显示MainWindow。
结果: 当我单击按钮时,看起来UI线程被锁定。我可以看到DoWork方法通过命令行递增计数器,但UI被锁定直到它完成。我的研究表明 使用DoWork内部的UI做任何事情是一个很大的禁忌,你需要使用ProgressChanged进行UI更新。我已经这样做了,所以我不确定UI继续锁定我的原因是什么。我可以看到WorkerRunningUI显示,但它似乎挂起了。
MainWindow.xaml
<Window x:Class="BW_TEST.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Second Imp" HorizontalAlignment="Left" Margin="301,199,0,0" VerticalAlignment="Top" Width="75" Click="btn_SecondImpClick"/>
</Grid>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public WorkerRunningUI workerUI;
public MainWindow()
{
InitializeComponent();
}
private void btn_SecondImpClick(object sender, RoutedEventArgs e)
{
Worker workerObject = new Worker();
this.Hide(); // hide main application
workerObject.workerUI.Show();
workerObject.launchWorker(1);
workerObject.workerUI.Hide();
this.Show();
}
}
}
WorkerRunningUI.xaml
<Window x:Class="BW_TEST.WorkerRunningUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WorkerRunningUI" Height="300" Width="300">
<Grid Margin="0,0,-8,-1" Height="271" VerticalAlignment="Top" HorizontalAlignment="Left" Width="300">
<Label Name="WorkerLabel" Content="Label" HorizontalAlignment="Left" Margin="89,90,0,0" VerticalAlignment="Top" Width="103"/>
</Grid>
WorkerRunningUI.xaml.cs
public partial class WorkerRunningUI : Window
{
public WorkerRunningUI()
{
InitializeComponent();
}
}
Worker.cs
// This class is responsible for the BackgroundWorker logic
class Worker
{
public BackgroundWorker worker;
public WorkerRunningUI workerUI;
public Worker()
{
this.worker = new BackgroundWorker();
this.workerUI = new WorkerRunningUI();
this.worker.DoWork += worker_DoWork;
this.worker.RunWorkerCompleted += worker_RunWorkerCompleted;
this.worker.WorkerReportsProgress = true;
this.worker.ProgressChanged += worker_ProgressChanged;
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine("Progress Changed: " + e.ProgressPercentage.ToString());
this.workerUI.WorkerLabel.Content = e.ProgressPercentage.ToString();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine("RunWorkerCompleted: " + e.Result);
this.workerUI.Hide(); // hide loading app
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
int value = (int)e.Argument;
while (value < 1000)
{
this.worker.ReportProgress(value);
value++;
}
e.Result = value;
}
public void launchWorker(int i)
{
this.worker.RunWorkerAsync(i);
}
}