WPF:如何在需要检查控件状态的特定情况下执行多线程
本文关键字:情况下 多线程 执行 控件状态 检查 WPF | 更新日期: 2023-09-27 18:05:46
我的情况如下:
我有一个WPF应用程序,其中我有一个方法,需要很多时间来完成。我不想失去UI响应性,所以我想在另一个线程中调用那个方法。我不会在这里粘贴我的全部代码,因为它太长了,而是我写了这个简短的程序,它很好地代表了我正在处理的内容:
public void MainWindow()
{
InitializeComponent();
ProcessThread = new Thread(TimeConsumingMethod);
ProcessThread.Name = "ProcessThread";
ProcessThread.Start();
}
public void TimeConsumingMethod()
{
this.Dispatcher.Invoke(() =>
{
MytextBlock.Text = "new text";
MyOtherTextBlock.Text = "Hello";
});
for (int i = 0; i < 50; i++)
{
Debug.WriteLine("Debug line " + i);
}
if (MyRadioButton.IsChecked == false) //????????????????
{
while (true)
{
if (DateTime.Now >= timePicker.Value)
break;
}
}
OtherMethod();
}
实际上,我对上面的代码有两个问题:1. 每次我想访问UI控件在我的代码,我必须使用this.Dispatcher.Invoke() =>....
这是正确的事情吗?我的意思是,在我的方法中有一些地方(在我的实际代码中),我检查一些控件的状态,每次我需要做Dispatcher。调用的东西-没有更好的方式来访问这些控件?2. 在上面的代码中,最后有IF块-在该块中我检查我的RadioButton的状态。里面,如果,我有一个耗时的代码。我不能这样做:
this.Dispatcher.Invoke(() =>
{
if (MyRadioButton.IsChecked == false) //????????????????
{
while (true)
{
if (DateTime.Now >= timePicker.Value)
break;
}
}
});
这段代码会告诉我的UI线程处理这个if块-但我不想那样!这会导致整个UI冻结,直到IF块完成。我该如何处理这种情况?
好吧,有很多方法可以实现你想要做的事情。其中一个可能是这样的:
public MainWindow() {
InitializeComponent();
Initialize(); //do some intialization
}
private async void Timer_Tick(object sender, EventArgs e) {
if (DateTime.Now >= timePicker.SelectedDate) { //check your condition
timer.Stop(); //probably you need to run it just once
await Task.Run(() => OtherMethod()); //instead of creating thread manually use Thread from ThreadPool
//use async method to avoid blocking UI during long method is running
}
}
private readonly DispatcherTimer timer = new DispatcherTimer(); //create a dispatcher timer that will execute code on UI thread
public void Initialize() {
MytextBlock.Text = "new text";
MyOtherTextBlock.Text = "Hello"; //access UI elements normally
for (var i = 0; i < 50; i++) {
Debug.WriteLine("Debug line " + i);
}
if (MyRadioButton.IsChecked == false)
{
timer.Interval = TimeSpan.FromSeconds(10); // during init setup timer instead of while loop
timer.IsEnabled = true;
timer.Tick += Timer_Tick; //when 10 sec pass, this method is called
timer.Start();
}
}
public void OtherMethod() {
//long running method
Thread.Sleep(1000);
}
我添加了一些注释,但主要思想是这样的:
不要手动创建线程,使用ThreadPool
不要循环等待某事,使用计时器定期检查它
当你有I/O任务时使用异步方法