2011-05-17 104 views
1

我有一个VB.Net和WPF应用程序。应用程序的一部分使用“图像生成器”来计算图像。另一个是使用“计时器”来显示直方图。当使用发生器创建每秒约2帧时,CPU大约为零用量,图像创建正常并且直方图将在Timer中创建,全部为1秒。所有似乎都是完美的。为什么System.Windows.Threading.DispatcherTimer不触发事件?

如果我让我用自己的“图像生成器”计算图像大约20 FPS,而不是只有2,CPU会上升到20%,但计时器永远不会抛出一个事件。 GUI中的图像显示20FPS。如果我停止图像生成器,则立即触发其事件。

我不知道从哪里开始搜索。

Me.TimerCalc = New System.Windows.Threading.DispatcherTimer 
Me.TimerCalc.Interval = TimeSpan.FromMilliseconds(1000) 
Me.TimerCalc.Start 

Private Sub TimerCalc_Tick(sender As Object, e As System.EventArgs) Handles TimerCalc.Tick 
'Does not fire if other process is running by using more CPU 
End Sub 

如果我降低帧率10FPS左右,有时DispatcherTimer抛出他的事件,somethimes没有。如果我增加帧率,DispatcherTimer将会抛出更少的事件。

编辑 下载演示项目位置:VisualStudio 2010 Dispatcher Test with Windows Form Timer

编辑 视频演示在这里上传:Video where cube does not rotate anymore

+0

理解消息循环是Windows GUI编程的基础。在您的代码闲置之前,Tick不会触发。 – 2011-05-17 19:31:10

回答

3

我不能在我结束复制此问题。这对我来说可以。

但是我不知道你可能在TimerCalc_Tick函数中做什么。你在那里做的任何事情都会阻塞Dispatcher。该活动在该活动完成之前不会再次启动。所以我可以肯定地看到,搞砸了。

看代码多一些,看着视频,并用它在我的机器上播放后,我觉得你只是挨饿的调度,当你起床到更高的数据速率。我不确定矩形为什么会完全停止旋转(对我来说不这样做),但如果你的处理器/显卡比我的低,我可以看到这是差异。当我像您在视频中一样向左滑动滑块时,我的处理器(所有四个内核)的挂钩率约为40%。低端机器会比这更糟糕,并且可以想象会挨饿其他线程。

如果你把这个项目,因为它上面贴的,你只是做一个单一的变化,把这个:这个

Public Sub New() 
    Me.TimerRefresh = New System.Windows.Forms.Timer 
    Me.TimerRefresh.Interval = Me.Intervall 
    Me.TimerRefresh.Enabled = True 
End Sub 

Public Sub New() 
    Me.TimerRefresh = New System.Windows.Forms.Timer 
    Me.TimerRefresh.Interval = Me.Intervall 
    Me.TimerRefresh.Enabled = False 
End Sub 

,这样你实际上并不启动需要所有处理的计时器,然后运行应用程序并将滑块一直运行到左侧,矩形仍然停止?如果没有,那么我相信你只是挨饿了Dispatcher。如果它......然后我仍然困惑。

+0

非常感谢你的答案添。 '私人小组TimerCalc_Tick(发送者为对象,E作为System.EventArgs)把手TimerCalc.Tick 的Debug.WriteLine( “TimerCalc_Tick:” &DateTime.Now.Ticks) 结束Sub' – goldengel 2011-05-17 18:31:40

+0

这就是你在干什么?人力资源管理。还有其他事情正在发生。我可以在示例应用程序中放入相同的代码,即使每秒钟执行100次也能正常工作(我不确定它实际上达到了那个速度,但是我为了看看会发生什么而碰到它)。您是否试过在示例项目中剥离代码以尝试隔离问题? – Tim 2011-05-17 18:38:47

+0

我已上载于顶部的示范项目。 – goldengel 2011-05-17 19:44:11

0

如果您希望短而稳定的时间间隔使用多媒体计时器(代码项目站点上找到点网包装)。

如果您需要做UI的线程工作,呼吁多媒体计时器的事件调度程序(未调度定时器)。将调度程序优先级设置为输入以确保UI不会阻止它。 确保操作比间隔少得多。

推荐使用5mSec以上的间隔。

0

分派器更新图像时被阻止。通过使用新的线程解除阻止。

Private Sub cImageGenerator_NewImageAvailable() Handles cImageGenerator.NewImageAvailable 
     If _IsReady = False Then Exit Sub 
     _IsReady = False 
     ' ################ 
     ' # Thread - Christian Zech 
     ' ################# 
     Dim trd As New System.Threading.Thread(Sub() 
                ' ########################## 
                ' # Clone 
                ' ########################## 
                Dim bm As System.Drawing.Bitmap = Me.cImageGenerator.CreateBitmap '.Clone 
                Dim imgSrc As ImageSource = BitmapToWpfBitmapSource(bm) 
                imgSrc.Freeze() 'needed because otherwise we will get the error: The calling thread cannot access this object because a different thread owns it. 
                Me.Dispatcher.Invoke(New Action(Of ImageSource)(AddressOf UpdateImage), imgSrc) 
               End Sub) 
     trd.SetApartmentState(System.Threading.ApartmentState.STA) ''ToDo: MTA probieren 
     trd.Name = "cImageGenerator_NewImageAvailable" 
     trd.Start() 
    End Sub 

    Private Sub UpdateImage(ByVal img As ImageSource) 
     Me.img1.Source = img 
     _IsReady = True 
    End Sub 
相关问题