这是我的情况:
我有一个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.invoke事情 - 是不是有更好的方法来访问这些控件?
2.在上面的代码中,最后有IF块 - 在该块中我正在检查我的RadioButton的状态。在那个IF中,我有一个耗时的代码。我不能这样做:
this.Dispatcher.Invoke(() =>
{
if (MyRadioButton.IsChecked == false) //????????????????
{
while (true)
{
if (DateTime.Now >= timePicker.Value)
break;
}
}
});
该代码将告诉我的UI线程如果阻止处理这个 - 但我不希望这样!这将导致整个UI冻结,直到此IF块完成。我应该如何处理这种情况?
答案 0 :(得分:0)
嗯,有很多方法可以实现您想要做的事情。其中一个可能看起来像这样:
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任务时使用异步方法