在不暂停UI的情况下休眠

时间:2014-07-22 17:10:53

标签: c# wpf user-interface sleep thread-sleep

我写了这个简单的程序,等待2秒,然后更新文本框:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 10; i++)
            {
                doSomething(i);
            }
        }
        public void doSomething(int i)
        {
            System.Threading.Thread.Sleep(2000);
            textBox1.Text += "this is the " + i + "th line\n";
        }
    }
}

但是当我运行它时,UI会暂停,我无法对UI做任何事情。它不是动态的,所有必须在textbox1上显示的文本都会在运行结束时显示。

有没有替代System.Threading.Thread.Sleep?

的替代品

3 个答案:

答案 0 :(得分:5)

您可以在不阻止UI线程的情况下使用async/await

for (int i = 0; i < 10; i++)
{
    await doSomething(i);
}

public async Task doSomething(int i)
{
    await Task.Delay(2000);
    this.Text += "this is the " + i + "th line\n";
}

答案 1 :(得分:3)

问题是你在UI线程上睡觉 。因此,UI会在你睡觉之前不会更新。

在您的情况下,理想情况是使用DispatcherTimer而不是在UI线程上休眠。

private void button1_Click(object sender, RoutedEventArgs args)
{
    int i = 0;
    DispatcherTimer timer = new DispatcherTimer();
    timer.Interval = TimeSpan.FromSeconds(2);
    timer.Tick += (s, e) =>
    {
        if (i == 10)
        {
            timer.Stop();
        }
        else
        {
            textBox1.Text += "this is the " + i + "th line\n";
            ++i;
        }
    };
    timer.Start();
}

注意 - 我建议使用DispatcherTimer而不是Timer类,因为Timer在后台线程上执行其Elapsed事件处理程序,因此要更新UI,您必须委托代码UI调度程序。但是DispatcherTimer在UI线程本身上执行Tick事件处理程序,因此不需要在UI调度程序上编组回来。

答案 2 :(得分:1)

简单的方法:

private void button1_Click(object sender, RoutedEventArgs e)
{
    DoSomethingAsync();
}

private async void DoSomethingAsync()
{
    for (int i = 0; i < 10; i++)
    {
        await doSomething(i);
    }
}

async Task doSomething(int i)
{
    await Task.Delay(1000);
    textBox1.Text += "this is the " + i + "th line\n";
}