如何在 WPF 应用程序的 RichTextBox 中记录时间?

Posted

技术标签:

【中文标题】如何在 WPF 应用程序的 RichTextBox 中记录时间?【英文标题】:How can I record time now in RichTextBox in WPF application? 【发布时间】:2020-03-02 11:16:00 【问题描述】:

这是我的代码,主要的 xaml.cs 文件:

//using statements...

namespace WpfAppTestRichTextBox

    public partial class MainWindow : Window
    
        public Paragraph p = new Paragraph();

        public MainWindow()
        
            InitializeComponent();
            Start();
        

        // Initialize the richTextBox...
        public void Start()
        
            Run r = new Run("");
            p.Inlines.Add(r);
            richTextBox.Document.Blocks.Add(p);
        

        // Button Click and Start a new Thread to record time for each second.
        private void Button_Click(object sender, RoutedEventArgs e)
        
            System.Threading.Thread th = new System.Threading.Thread(ChangeText);
            th.Start();
        

        public void ChangeText()
        
           while(true)
           
                this.Dispatcher.Invoke(new Action(() =>
                

                    string time = System.DateTime.Now.ToString() + "\n";
                    Run r = new Run(time);
                    p.Inlines.Add(r);

                    System.Threading.Thread.Sleep(1000);

                ));
            
        
    


我将新的 Run() 添加到 Paragraph 并期望richTextBox 的内容将被刷新。但它在 while() 中阻塞并且在richTextBox 中什么也不打印。

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

问题是您在调度程序线程中处于睡眠状态。您是否打算在调度程序调用之后放置它?

while(true)

    this.Dispatcher.Invoke(new Action(() =>
    
        string time = System.DateTime.Now.ToString() + "\n";
        Run r = new Run(time);
        p.Inlines.Add(r);
    ));
    System.Threading.Thread.Sleep(1000);

Thread.Sleep

在指定的时间内暂停当前线程。

Dispatcher.Invoke 调度块内的代码以在 UI 线程上运行。将睡眠放在那里会挂起 UI 线程,本质上会导致它冻结。

更新:更好的解决方案是使用调度程序计时器。

public partial class MainWindow : Window

    private DispatcherTimer _timer = new DispatcherTimer();
    public Paragraph p = new Paragraph();

    public MainWindow()
    
        InitializeComponent();
        _timer.Interval = new TimeSpan(0, 0, 1);
        _timer.Tick += _timer_Tick;
    


    private void _timer_Tick(object sender, EventArgs e)
    
        string time = System.DateTime.Now.ToString() + "\n";
        Run r = new Run(time);
        p.Inlines.Add(r);
    

    private void Button_Click(object sender, RoutedEventArgs e)
    
        Run r = new Run("");
        p.Inlines.Add(r);
        richTextBox.Document.Blocks.Add(p);
        _timer.Start();
    

【讨论】:

它对我有用!但我认为它只是休眠 1000 毫秒。为什么 Sleep() 语句会阻塞 UI 线程? 我在回答中添加了更多细节。【参考方案2】:

首先,将您的方法更改为异步是一个好主意,但要回答您的问题,您的 UI 可能只是由于方法永无止境或将控制权交还给调用者而没有刷新。尝试强制刷新:

 if (richTextBox.InvokeRequired)
 
      richTextBox.Invoke(new MethodInvoker(delegate
      
          richTextBox.Refresh();

       ));
 
 else richTextBox.Refresh();
 Application.DoEvents();

如果这不起作用,请尝试在调试模式下运行并在特定时间检查 p 的值,或者尝试直接更改 textbox.Text 的值以查看您的实际错误在哪里

【讨论】:

以上是关于如何在 WPF 应用程序的 RichTextBox 中记录时间?的主要内容,如果未能解决你的问题,请参考以下文章

WPF RichTextBox 如何滚动到光标所在位置滚动条操作

如何使用实体框架将 RichTextBox 内容存储到 WPF 中的 SQLServer 数据库

wpf中如何让richtextbox的滚动条显示

C#/WPF:禁用 RichTextBox 的文本换行

wpf中richtextbox如何改变行高

已解决如何从(MySQL)表中检索 RichText 内容到 WPF RichTextBox