我在我的UI(WPF)線程中創建了一個BackgroundWorker(mainBw
)。它有一個無限循環,睡眠時間爲1.5秒,通過Application.Current.Dispatcher.Invoke
調用一個函數,該函數只將文本從「global」text
變量輸出到TextBox。.NET BackgroundWorker:我不明白ReportProgress是如何工作的
還在循環之前它創建了另一個(child
)BackgroundWorker其中ReportsProgress在ProgressChanged事件處理程序中修改text
變量。
我以爲它不會工作,因爲沒有任何像WinForms Application.DoEvents()mainBw
循環中的任何東西,所以它無法處理事件處理程序。但它的工作。爲什麼?
下面是代碼:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows;
namespace WpfApplication6
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private BackgroundWorker mainBw = new BackgroundWorker();
private void Button_Click(object sender, RoutedEventArgs e)
{
mainBw.DoWork += MainBwOnDoWork;
mainBw.RunWorkerAsync();
btn.IsEnabled = false;
}
private string text = "abc";
private void MainBwOnDoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += BwOnDoWork;
bw.ProgressChanged += BwOnProgressChanged;
bw.WorkerReportsProgress = true;
bw.RunWorkerAsync();
while (true)
{
Thread.Sleep(1500);
text += " main ";
Application.Current.Dispatcher.Invoke(new Action(() => { WriteToUIThread(); }));
}
}
private void WriteToUIThread()
{
tbox.Text = DateTime.Now + " " + text + Environment.NewLine + tbox.Text;
}
private void BwOnProgressChanged(object sender, ProgressChangedEventArgs e)
{
text += e.UserState.ToString();
}
private void BwOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
while (true)
{
Thread.Sleep(3000);
(sender as BackgroundWorker).ReportProgress(0, "child");
}
}
}
}
// XAML
<Window x:Class="WpfApplication6.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 Name="btn" Content="Button" HorizontalAlignment="Left" Height="105" Margin="43,47,0,0" VerticalAlignment="Top" Width="165" Click="Button_Click"/>
<TextBox Name="tbox" HorizontalAlignment="Left" Height="114" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="456" Margin="27,182,0,0"/>
</Grid>
</Window>
因爲UI線程未被鎖定。一旦'BwOnProgressChanged'函數完成後,UI線程就可以自由地更新顯示內容(或者在那裏,它可能不得不在其間做一些其他的小事) – musefan
@musefan,據我瞭解,事件在mainBw中處理線程,而不是在UI線程中。如果我做這樣的事情 tbox.Text =「child」; 在ProgressChanged事件中,它會拋出異常。 – AlexP11223
真的嗎? tbox.Text =「小孩」;在ProgressChanged事件中引發異常? – Paparazzi