2016-01-06 56 views
0

使用Visual Studio 2015,Visual C#windows應用程序。定時器運行在與創建它不同的線程中

我需要一個計時器,清空主線程中的隊列,因爲一些UI組件被修改。我這個編碼:

public Form1() 
    { 
     InitializeComponent(); 
     Q = new ConcurrentQueue<amsg>(); 
     timer = new System.Timers.Timer(100); 
     timer.Elapsed += timer_Elapsed; 
     timer.Enabled = true; 
    } 

    void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     clsUdpMsg msg; 
     while (Q.TryDequeue(out msg)) handleRx(msg); 
    } 

,但經過的事件在輔助線程執行...?

如果我把一個計時器在設計時在主窗體上生成的原型是稍有不同:

private void timer1_Tick(object sender, EventArgs e) 
    { 
     amsg msg; 
     while (Q.TryDequeue(out msg)) handleRx(msg); 
    } 

但一個人在主線程上下文中執行。

這個問題延伸到任何創建一個計時器的線程;我認爲在線程中創建的計時器在同一個線程上下文中執行已用過的事件。我錯過了什麼嗎?

快速編輯:我看到這些是不同的定時器,System.Timers.Timer和Windows.Forms.Timer。那麼 - 我如何可靠地創建將在創建它們的線程中執行的定時器?

+1

他們是2個不同的計時器。第一個來自'System.Timers','Windows.Forms.Timer'是第二個 – Plutonix

+0

.net中有4個定時器,還有'System.Threading.Timer'和'System.Windows.Threading。DispatcherTimer'也 –

回答

4

是的,你只是處理兩個單獨的Timer類。 System.Windows.Forms.Timer在主線程上觸發Tick事件,System.Timers.Timer在後臺線程上觸發Elapsed事件。 System.Windows.Forms.Timer的優點是它隱藏了線程; System.Timers.Timer的優點是它不需要消息泵工作。

你問,「我如何可靠地創建將在創建它們的線程中執行的計時器?」好吧,當你有一個Windows窗體GUI並且在UI線程上啓動Timer時,這很容易:只需使用System.Windows.Forms.Timer即可。如果你沒有消息泵來利用,你必須使用System.Timers.Timer,並且當計時器觸發Elapsed事件時,在主線程上運行某些東西的唯一方法是重新創建類似主消息循環的東西線程 - 讓它坐下,也許等待Monitor.Pulse或其他類型的計時器線程通知。但是這意味着你的主線程不會在這段時間內完成任何有用的工作......

+0

所以它看起來最好的做法是假設所有計時器事件不是線程安全的...在這種情況下,我可以使用Windows計時器。感謝閃電般的快速解答! – user3235770

+0

我不太喜歡你在這裏。 「所有計時器事件不是線程安全的」是什麼意思? – adv12

+1

事件是線程安全的,問題是您的處理程序是否是。如果你不必擔心UI線程,那麼如果可能的話,最好的辦法就是擁有一個線程安全處理程序,這樣你就不必關心它運行的線程了。 –

0

這不是直接回答你的問題,而是一個避免定時器線程問題的建議。

你總是可以使用微軟的Reactive Framework(NuGet「Rx-WinForms」)。

您的代碼應該是這樣的:

var subject = new Subject<clsUdpMsg>(); 

var subscription = 
    subject 
     .ObserveOn(this) 
     .Subscribe(msg => handleRx(msg)); 

subject替換您Q。每當你想添加一條消息,你只需撥打subject.OnNext(msg)

即使在後臺線程上對subject.OnNext(msg)進行調用,.ObserveOn(this)也會將回調收回回UI。

如果您想停止訂閱,請致電subscription.Dispose()

相關問題