WPF:如何在我需要检查控件状态的给定情况下进行多线程处理

时间:2016-09-05 13:05:24

标签: c# wpf multithreading

这是我的情况:

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

1 个答案:

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

我已经添加了一些评论,但主要的想法是:

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

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

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