2

我有一个名为“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。我在这里做错了什么?

4

5 回答 5

3

Doesn't matter what technology I think.

The code is running on the same thread, meaning the the UI won't be updated untill all the code on that thread is completed. You should address a different thread to update that textblock.

In that case, you will have 2 thread:

  • The origininal thread, executing the "lots and lots of code"
  • The second (extra) created thread, which will handle updating the textblock's text while the other thread is executing the other code.

I've created a little something that should resolve your problem, it's based on this Stack Overflow page

于 2012-08-20T11:14:52.800 回答
1

You should look into the UI threading concept of WPF. Invoke the Dispatcher to modify the textbox. Also the search should run with 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.");
});
于 2012-08-20T11:15:39.300 回答
1

Since this is WPF, try the following: after changing the text to "Processgin", call:

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

This will tell the thread to update the UI as soon as possible.

于 2012-08-20T11:17:23.603 回答
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."
   });
}
于 2012-08-20T11:25:35.107 回答
0

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

于 2012-08-24T11:30:23.297 回答