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块完成。我该如何处理这种情况?

WPF:如何在需要检查控件状态的特定情况下执行多线程

好吧,有很多方法可以实现你想要做的事情。其中一个可能是这样的:

    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);
    }

我添加了一些注释,但主要思想是这样的:

  1. 不要手动创建线程,使用ThreadPool

  2. 不要循环等待某事,使用计时器定期检查它

  3. 当你有I/O任务时使用异步方法