C# TextBlock不会更新

C# TextBlock不会更新,c#,wpf,multithreading,textblock,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("

我有一个名为“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秒钟,在它结束时,它会再次更改findListText中的文本

private void Find(bool? bForward = true)
{
    {
        //Lots and lots of code
    }
    findListText.Text = "Search completed."
}
问题是,文本块似乎从未更新为“正在处理请求。请稍候…”。文本块处于原始状态,10秒后更新为“搜索完成”,似乎跳过了中间人


我用的是C#WPF。我做错了什么?

我认为什么技术无关紧要

代码在同一个线程上运行,这意味着在该线程上的所有代码完成之前,UI不会被更新。您应该寻址不同的线程来更新该文本块

在这种情况下,您将有2个线程:

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

我已经创建了一个可以解决您的问题的工具,它基于堆栈溢出页面

您应该研究WPF的UI线程概念。调用
调度程序
修改文本框。此外,搜索应与
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.");
});

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


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

以下是如何在自己的线程中运行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."
   });
}

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

我们在谈论什么技术?WPF?赢表格?Web表单?这是什么技术?WinForms、WPF、Silverlight、ASP.NET?顺便说一句,如果
,则不需要先使用该
。只需将其更改为
hicenter=e.Key==Key.Return它是一个xaml表单-不是基于web的。也就是说,WPF。我想这正是问题所在,但我不确定如何创建一个单独的线程来更新textblock。你不需要所有这些,你所要做的就是更新UI。请检查我的答案并给我任何反馈。@AndreCalil:你的答案就是这里描述的,除非你不检查对象是否为线程所有。@djerry我不明白你提供的链接如何在我的特定情况下使用。你能帮我澄清一下吗?谢谢。你说得对,这个解决方案是针对一个稍微不同的问题。我将更新答案,并在解决方案应用程序上做更多工作。@djerry确实如此。然而,就我们所知,这个应用程序是一个单一线程。我在这方面取得了一些成功。我基本上有两个搜索函数,一个需要毫秒,另一个需要10秒。如果我将这行代码用于短搜索,则会出现“处理请求”消息,即使只是一瞬间。在10秒长的搜索中使用这一行代码时,什么也没有发生。这个修复程序是一帆风顺的,并不是处理这些情况的正确方法。想想看,如果UI线程忙于工作,UI如何更新?这种情况正是创建
BackgroundWorker
的原因。@Robbo905您在长时间处理之前是否尝试过更改文本?@AndreCalil确实,“处理请求”消息应该在任何搜索发生之前出现。如前所述,这在非常短的搜索中有效,但在10秒的挂起搜索中无效。我不确定从哪里开始。我似乎得到了一个“'System.Threading.ThreadPool'不包含'QueueWorkerItem'的定义”错误。尽管如此,它仍然不是完美的。
private void Find(bool? bForward = true)
{
   {
       //Lots and lots of code
   }
   Dispatcher.BeginInvoke((Action) delegate {
      findListText.Text = "Search completed."
   });
}