我已经尝试了这段代码的很多变体。 无论如何,我都收到了同样的问题。 UI 更新开始正常,然后停止,直到整个过程完成。 有人可以指出我正确的方向吗?

场景

在 WPF 应用程序中,我们将使用不同的参数调用相同的 API 数千次。 我们需要收集所有的回应并做一些事情。

示例代码

List<Task> tasks = new List<Task>();

for (int i = 1; i <= iterations; i++)
{
   Task t = SampleTask(new SampleTaskParameterCollection { TaskId = i, Locker = locker, MinSleep = minSleep, MaxSleep = maxSleep });
   tasks.Add(t);
}

Task.WhenAll(tasks);
private void SampleTask(SampleTaskParameterCollection parameters)
{
   int sleepTime = rnd.Next(parameters.MinSleep, parameters.MaxSleep);
   Thread.Sleep(sleepTime);

   Application.Current.Dispatcher.BeginInvoke(new Action(() =>
   {
      lock (parameters.Locker)
      {
         ProgressBar1.Value = ProgressBar1.Value + 1;
         LogTextbox.Text = LogTextbox.Text + Environment.NewLine + "Task " + parameters.TaskId + " slept for " + sleepTime + "ms and has now completed.";
      }
      LogTextbox.ScrollToEnd();

      if (ProgressBar1.Maximum == ProgressBar1.Value)
      {
         RunSlowButton.IsEnabled = true;
         RunFastButton.IsEnabled = true;
         ProgressBar1.Value = 0;
      }
   }), System.Windows.Threading.DispatcherPriority.Send);
}

当前存储库位于GitHub 上 看看简单窗口。

#1楼 票数:1 已采纳

不要创建数以千计的任务——这会导致巨大的性能问题。

相反,使用Parallel.For()类的东西来限制同时运行的任务数量; 例如:

Parallel.For(1,
    iterations + 1,
    (index) =>
    {
        SampleTask(new SampleTaskParameterCollection { TaskId = index, Locker = locker, MinSleep = minSleep, MaxSleep = maxSleep });
    });

此外,如果 UI 更新花费的时间比调用BeginInvoke()的时间间隔长,那么调用将开始排队,事情会变得很糟糕。

为了解决这个问题,您可以在 SampleTask() 中使用一个计数器,每 N 次调用才实际更新一次 UI(使用合适的 N 值)。

但是,请注意,为避免线程问题,您必须在递增和检查计数器值时使用Interlocked.Increment() (或其他一些锁)。 您还必须确保在所有工作完成后最后一次更新 UI。

  ask by Chris Felstead translate from so

未解决问题?本站智能推荐:

1回复

在 WPF 应用程序中运行多个后台任务 - UI 更新停滞

我已经尝试了这段代码的很多变体。 无论如何,我都收到了同样的问题。 UI 更新开始正常,然后停止,直到整个过程完成。 有人可以指出我正确的方向吗? 场景 在 WPF 应用程序中,我们将使用不同的参数调用相同的 API 数千次。 我们需要收集所有的回应并做一些事情。 示例代码 当前存储库位
1回复

如何从线程更新WPF应用程序中的UI?

我正在编写一个客户端/服务器应用程序,并且试图从包含无限循环的线程更新UI,以便执行Socket.Receive。 当我在套接字上收到数据包时,我必须更新UI并继续循环。 问题是线程无法管理UI,因此我尝试在线程内部调用BeginInvoke,但结果是UI冻结。 是否有一个简单的过程允许在
2回复

为什么要拆分未在UI线程上运行的任务,以使WPF应用程序更具响应性?

在第1部分“入门”中 亚历山德拉鲁西娜的系列。 .NET Framework 4中的并行编程 为了使WPF UI响应,它通过将密集型计算外包出UI来完成。 最终,代码更改为: 更新: 将密集计算从UI线程中移出。 以下是来自Part1文章的引言: “
3回复

在 WPF 应用程序的后台执行任务

例子 如果我想让Start() ,推荐的方法是什么(TAP 或 TPL 或 BackgroundWorker 或 Dispatcher 或其他) 不阻塞 UI 线程 提供进度报告 可取消 支持多线程
3回复

任务不会更新WPF中的UI

我写了这段代码: 它在WPF中有效,但是当我以这种方式编写此代码时; 它不起作用,而txtReport.Text具有正确的值,但是在操作中间不显示,但是当操作结束时txtReport显示它的值 为什么这段代码不起作用?
1回复

C#WPF更新UI应用程序冻结

在C#中,我们知道有多个背景线程...这样我们可以创建多个UI线程吗? 和多个UI线程可帮助您在没有freeez的情况下更新观察数据集中的数据? 如果不是,从Web服务获取数据并更新到观察集合的最佳方法是什么。 码:-
2回复

ReactiveUI 6异步命令未在WPF应用程序中的后台线程上运行

视图模型 并且View有一个<Button Command="{Binding GetApplicationExtensions}"></Button> 。 实现GetApplicationExtensions 从我读过的关于ReactiveUI的所
4回复

使用WPF应用程序的UI线程对UI元素执行长时间的处理任务,还可以在同一窗口上更新进度条

我的程序由一个大型图形UI控件组成,我不时需要花费大约15秒钟重新加载一次。 因为更新代码主要与UI控件一起工作(也许其中90%实际上是在控件上设置属性),所以实际上让UI线程来处理它对我来说很有意义。 我真的不希望控件在从UI加载到单独的线程中时以视觉方式重新绘制。 我还希望更新进度
1回复

如何在WPF应用程序中查找使用自己的UI线程运行的窗口

我有一个使用WPF Window和自己的Dispatcher作为启动启动窗口的应用程序。 此初始屏幕将向用户显示信息,并且是TopMost窗口。 我不想将其作为Application.MainWindow但必须在创建MainWindow之前将其显示... 在启动过程中或应用程序运行期间
4回复

定位并最大化在后台任务中运行的窗口

好的,以下问题: 我在一台PC上的多达10个屏幕上有一些窗口。 其中一些应该在后台任务中运行。 它是一个WPF应用程序,但是对于屏幕定位等,我使用WinForms的某些部分。 为此,我使用以下几行: 在此窗口中,我使用以下内容来定位它: 但是,当我进入“ var si