冻结UI和奇怪的线程行为(WPF)

时间:2016-05-25 05:32:57

标签: c# .net wpf multithreading caliburn.micro

我正在使用WPF和C#构建应用程序,我遇到了一个奇怪的问题。我的应用程序中有多个线程,其中许多是通过System.Timer计时器创建的。我可以采取特定的操作,这会导致我的应用程序的UI冻结;当这种情况发生时,我的UI将永久冻结。最奇怪的是,如果我用Threadpool.GetAvialbaleThreads检查可用线程的数量,如果我不停止应用程序,可用线程的数量将不断减少。我的应用程序中的所有线程都是通过计时器或Task.StartNew方法创建的。

我的代码中有几部分用于启动新线程,我将尝试以缩写的方式显示所有这些部分。

DataManager.cs

// Two System.Timers.Timer(s) handle generating data values on 3 second and 1.5 second intervals.
_averageTimer = new System.Timers.Timer(1000 * 3);
_averageTimer.Elapsed += GenerateNewAveragePoint;
_averageTimer.Enabled = false;

_flowGenTimer = new System.Timers.Timer(1000 * 1.5);
_flowGenTimer.Elapsed += GenerateNewFlowSet;
_flowGenTimer.Enabled = false;

// I also have a primary work loop in this class which is created via Task
// This function runs continuously
Task.Run(() => ProcessData());

// I also send off a Task to do file I/O about every 3 seconds
Task.Run(() =>
{
    lock (_sharedData.FileLock)
    {  
          _continuousFileManager.WriteDataSubset(tmpData);
    }
});

// Finally, I have a similar file I/O function to the one above, but it is
// called in the timer which fires every 3 seconds
Task.Run(() =>
{
    lock (_sharedData.FileLock)
    {  
          _averageFileManager.WriteDataSubset(tmpData);
    }
});

所以从这个类看来我可能最多使用6个线程。


在另一个类中,我有3次调用Dispatcher.Invoke

AdvancedPanel.cs

// RealtimeDataFlowItems is an ObservableCollection
Application.Current.Dispatcher.Invoke(delegate
{
      RealtimeDataFlowItems.Insert(0, avgFlow);
});

// RealtimeDataHRItems is an ObservableCollection
Application.Current.Dispatcher.Invoke(delegate
{
      RealtimeDataHRItems.Insert(0, avgFlow);
});

// RealtimeDataTimeItems is an ObservableCollection
Application.Current.Dispatcher.Invoke(delegate
{
      RealtimeDataTimeItems.Insert(0, avgFlow);
});


在另一个类中,我有一个调用Dispatcher.Invoke 的 DataInfo.cs

Application.Current.Dispatcher.Invoke(delegate
{
    IndicatorPoints = new PointCollection(new[] { /* Removed for brevity */});
}


在另一个类中有两个System.Timers.Timer,它们以15 ms和2秒的间隔执行。

PlotData.cs

_plotTimer = new System.Timers.Timer(15);
_plotTimer.Elapsed += ProcessLoop;
_plotTimer.Enabled = false;

_boundsTimer = new System.Timers.Timer(1000 * 2);
_boundsTimer.Enabled = false;
_boundsTimer.Elapsed += CheckYAxisBounds;

此外,该类使用OxyPlot绘图库,以便在UI中显示实时数据。 OxyPlot显然必须修改UI,因此将在UI线程上执行操作。



最后,我在我的应用程序中使用Caliburn.Micro并大量使用它的EventAggregator。每次我希望发布消息时,都会使用StartNew方法启动新任务。我的应用程序中几乎所有类都以某种身份使用EventAggregator,因此可以从这些操作中使用多个线程。

我希望这些信息对您有所帮助,如果有更多我应该提供的信息,请告诉我。我希望你们中的一个能够向我提供有关可能发生的事情的任何见解,以及我如何能够调试和解决我的UI冻结问题。非常感谢你的帮助!

0 个答案:

没有答案