wpf 在 while 循环中更改的标签不会更新 UI

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25414964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 12:23:03  来源:igfitidea点击:

Label changed in while loop does not update UI

c#wpfloops

提问by kk6axq

When running this code:

运行此代码时:

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()
    {
        while (true)
        {

            InitializeComponent();

            DateTime dtCurrentTime = DateTime.Now;
            label1.Content = dtCurrentTime.ToLongTimeString();
        }
    }

}
}

to update the label frequently, the window never opens. But when I remove the while loop it works but it just doesn't update the label... So how would I update the label to show the current time without any user input? Thanks, L

频繁更新标签,窗口永远不会打开。但是,当我删除 while 循环时,它可以工作,但它只是不更新​​标签......那么我将如何更新标签以显示当前时间而无需任何用户输入?谢谢,L

回答by Reed Copsey

The problem is that you're blocking your UI thread.

问题是你阻塞了你的 UI 线程。

You can't run code in a loop this way on the UI thread. You need to setup a Timer, and update your label in the timer, to allow the UI thread to continue executing and process messages.

您不能在 UI 线程上以这种方式循环运行代码。您需要设置一个Timer,并在计时器中更新您的标签,以允许 UI 线程继续执行和处理消息。

This can look like:

这看起来像:

public MainWindow()
{
        InitializeComponent();


        DispatcherTimer timer = new DispatcherTimer 
            {
                Interval = TimeSpan.FromSeconds(0.5)
            };
        timer.Tick += (o,e) =>
            {
                DateTime dtCurrentTime = DateTime.Now;
                label1.Content = dtCurrentTime.ToLongTimeString();
            };
        timer.IsEnabled = true;
}

This will cause the timer to update the UI two times per second.

这将导致计时器每秒更新 UI 两次。

回答by Johan Larsson

You can use Rx:

您可以使用Rx

using System;
using System.Reactive.Linq;
using System.Threading;

public MainWindow()
{
    InitializeComponent();
    Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1))
              .ObserveOn(SynchronizationContext.Current)
              .Subscribe(x => Label.Content = DateTime.Now.ToLongTimeString());
}

You probably don't want to add the dependency just for this though.

不过,您可能不想为此添加依赖项。

回答by d.moncada

You cannot block the UI. The UI thread needs to continue pumping messages. You can use a simple Taskwith BeginInvoketo achieve what you want.

您无法阻止 UI。UI 线程需要继续泵送消息。您可以使用简单的TaskwithBeginInvoke来实现您想要的。

    public MainWindow()
    {
        InitializeComponent();

        Task.Run(() =>
        {
            while (true)
            {
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    var dtCurrentTime = DateTime.Now;
                    label1.Content = dtCurrentTime.ToLongTimeString();
                }));
                Thread.Sleep(1000);
            }
        });
    }

回答by Jorri Fransen

Yes you are blocking the main Thread, use a Timer like this

是的,您正在阻塞主线程,请使用这样的计时器

public partial class Form1 : Form
{

    private Timer timer;
    public Form1()
    {
        InitializeComponent();

        timer = new Timer();
        timer.Interval = 1;
        timer.Tick += timer_Tick;
        timer.Enabled = true;
    }

    void timer_Tick(object sender, EventArgs e)
    {
        lblTime.Text = DateTime.Now.ToLongTimeString();
    }

}

回答by Deleted

You could try a do...whileloop to accomplish the same, this will run the code once (the dopart) and then continue to execute for the whilecondition.

您可以尝试使用do...while循环来完成相同的操作,这将运行一次代码(do部分),然后继续针对while条件执行。