2011-05-17 216 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 
相關問題