TextBlock不会更新

时间:2012-08-20 11:10:32

标签: c# wpf multithreading textblock

我有一个名为“findListText”的文本块。在这里,我正在更新其中的文字:

private void InstantSearch(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Return)
    {
        HitEnter = true;
    }
    findListText.Text = "Processing request. Please wait...";
    Find(bool.Parse("False" as string));
}

但是,下一组代码是一个搜索函数,最多可能需要10秒,在它结束时,它会再次更改find​​ListText中的文本。

private void Find(bool? bForward = true)
{
    {
        //Lots and lots of code
    }
    findListText.Text = "Search completed."
}

问题是,文本块似乎永远不会更新为“处理请求。请稍候......”。文本块处于原始状态,10秒后更新为“搜索完成。”,似乎正在跳过中间人。

我正在使用C# - WPF。我在这里做错了什么?

5 个答案:

答案 0 :(得分:3)

无论我认为什么技术都无所谓。

代码在同一个线程上运行,这意味着UI不会被更新,直到该线程上的所有代码都完成。您应该使用不同的线程来更新该文本块。

在这种情况下,你将有2个帖子:

  • 原始线程,执行“大量代码”
  • 第二个(额外)创建的线程,它将处理更新文本块的文本,而另一个线程正在执行其他代码。

我已经创建了a little something来解决您的问题,它基于this Stack Overflow页面

答案 1 :(得分:1)

您应该研究WPF的UI线程概念。调用Dispatcher修改文本框。此外,搜索应与ThreadPool.QueueWorkerItem一起运行。

// Start worker thread
ThreadPool.QueueUserWorkItem(state =>
{
    // Long running logic here
   findListText.Dispatcher.BeginInvoke(() => findListText.Text = "Processing request. Please wait...");
   Find(bool.Parse("False" as string)); 


    // Tip: Run change on GUI thread from the worker using the dispatcher
    findListText.Dispatcher.BeginInvoke(() => findListText.Text = "Search completed.");
});

答案 2 :(得分:1)

由于这是WPF,请尝试以下操作:将文本更改为“Processgin”后,请调用:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { this.UpdateLayout(); }));

这将告诉线程尽快更新UI。

答案 3 :(得分:1)

以下是如何在自己的线程中运行find方法。

private void InstantSearch(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Return)
    {
        HitEnter = true;
    }
    findListText.Text = "Processing request. Please wait...";
    BackgroundWorker tempWorker = new BackgroundWorker();
    tempWorker.DoWork += delegate
    {
       Find(bool.Parse("False" as string));
    };
    tempWorker.RunWorkerAsync();
}

如果您尝试这样做,您将收到错误,因为您从后台线程访问您的UI线程。因此,您还需要更新find方法。

private void Find(bool? bForward = true)
{
   {
       //Lots and lots of code
   }
   Dispatcher.BeginInvoke((Action) delegate {
      findListText.Text = "Search completed."
   });
}

答案 4 :(得分:0)

我刚刚回到这里,并在互联网上浏览了类似的问题。对于像在长时间运行的进程发生之前推送单个消息这样简单的事情,我很惊讶没有人建议“Application.DoEvents();”。是的,我知道它有它的缺点,我的UI仍然会挂起,但这至少适合我的情况。

相关问题