3

我一直在分析一个 WPF 应用程序,它基本上从服务器获取数据并在 GUI 中显示数据。

这段代码不是我的,并且应用程序存在与 GUI 响应缓慢有关的问题,我正在尝试找出导致该问题的原因。

我想与您分享我的想法,即问题可能出在哪里,我想听听您对此有何看法,无论这是否有意义。

为了从服务器获取数据,应用程序使用了 7 个线程(这样做主要是因为应用程序逻辑,所以不要太在意为什么是 7 而不是一个......),现在,每个线程都是通过调用一个名为 CreateThreadForTask() 的方法创建的

public void StartAllThreads()
{
    this.CreateThreadForTask(Tasks.Task1);
    this.CreateThreadForTask(Tasks.Task2);
    this.CreateThreadForTask(Tasks.Task3);
    this.CreateThreadForTask(Tasks.Task4);
    this.CreateThreadForTask(Tasks.Task5);
    this.CreateThreadForTask(Tasks.Task6);
    this.CreateThreadForTask(Tasks.Task7);
}

public void CreateThreadForTask(Tasks task)
{
    ... // this part of the code is not important
    
    //! Initialize and start timer
    timer = null;
    timer = new DispatcherTimer();
    timer.Tick += new EventHandler(RunMainSyncForTask);
    timer.Start();  
}

public void RunMainSyncForTask(object s, EventArgs e)
{
    int sec = int.Parse(AppSettings.GetSetting("syncInterval"));
    timer.Interval = new TimeSpan(0, 0, sec);
    
    //threadCaller is a background worker
    threadCaller = InitializeThread();
    threadCaller.DoWork += DoWorkEventHandler(StartSync);
    threadCaller.RunWorkerAsync();
}

当我调试代码时,我注意到所有线程都是使用 DispatcherTimer 创建的;我认为应用程序正在创建 7 个 DispatcherTimer,并将计时器的 Tick 事件与 RunMainSyncForTask() 方法链接起来,该方法在内部创建一个后台工作程序,从服务器获取数据并将该数据保存到本地数据库。

现在,这是从 MSDN

DispatcherTimer 在每个 Dispatcher 循环的顶部重新评估。

定时器不能保证在时间间隔发生时准确执行,但可以保证在时间间隔发生之前不会执行。这是因为 DispatcherTimer 操作像其他操作一样放置在 Dispatcher 队列中。DispatcherTimer 操作何时执行取决于队列中的其他作业及其优先级。

因此,基于此,我相信每次计时器执行滴答事件时应用程序都会向线程发送垃圾邮件,并且同时执行 7 次;由于 DispatcherTimer 的性质,所有这些操作都被添加到 Dispatcher 队列中,由于 Dispatcher 正忙,这使得 GUI 响应变慢。

此外,该应用程序的另一个问题是,当它运行时,它会占用大约 90-95% 的 CPU,我认为如果我的假设是正确的,这也可能是导致此问题的原因。

所以如果你能分享一些关于这个的内幕,我会很感激的。

谢谢。

4

1 回答 1

1

您获得了 90-95% 的 CPU,因为您已经通过疯狂的线程调用网络建立了一种忙碌等待的形式。

如果您使用此StartSync逻辑来发布状态通知或将数据返回到 GUI,那么您会遇到很多麻烦。如果您使用的是 .Net 4.0,您应该切换到Task Parallel Library并让框架为您处理所有这些。它还支持优雅取消等。

如果您不想使用 TPL,我建议您改为将Windows Dispatcher(使用通常的嫌疑人:Invoke 或 BeginInvoke)或SynchronizationContext(与 异步,与Post同步Send)传递给各个任务,以用于这些必须在图形用户界面。

于 2011-03-17T22:40:17.700 回答