【问题标题】:How can I record time now in RichTextBox in WPF application?如何在 WPF 应用程序的 RichTextBox 中记录时间?
【发布时间】: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 中什么也不打印。

我该如何解决这个问题?

【问题讨论】:

    标签: c# wpf windows multithreading user-interface


    【解决方案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 的值以查看您的实际错误在哪里

    【讨论】:

      猜你喜欢
      • 2011-04-11
      • 2011-12-25
      • 2016-07-23
      • 1970-01-01
      • 1970-01-01
      • 2012-05-27
      • 1970-01-01
      • 1970-01-01
      • 2021-09-22
      相关资源
      最近更新 更多