簡體   English   中英

System.Windows.Forms.Timer沒有觸發

[英]System.Windows.Forms.Timer not firing

我想使用System.Windows.Forms.Timer來確保在我正在創建的excel插件的UI線程上觸發事件。 我按如下方式構建計時器:

private System.Windows.Forms.Timer _timer;

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    Debug.WriteLine("ThisAddIn_Startup:" + Thread.CurrentThread.ManagedThreadId);

    _timer = new System.Windows.Forms.Timer();
    _timer.Tick += new EventHandler(TimerEventHandler);
    _timer.Interval = 500;            
}

計時器是由我正在使用的庫中的COM事件觸發的:

private void OnEvent()
{
    _timer.Start();
}

然后我希望_timer_timer時調用以下方法:

public void TimerEventHandler(object sender, EventArgs args)
{
    _timer.Stop();
    Debug.WriteLine("Tick: " + Thread.CurrentThread.ManagedThreadId);                  
}

據我所知,當我在Addin線程中創建計時器時,即使它是從另一個線程啟動的(在這種情況下是COM事件),它應該觸發它創建的線程,即插件線程。 但是,這不會發生。

我已經在我過去編寫的RTDServer實現了這個確切的機制( 如Kenny Kerr所述 )並且它按預期工作,但是這個場景中的_timer永遠不會_timer

我還閱讀了其他SO文章指出相同的行為,無法弄清楚我的插件設置有什么不同?

編輯:觸發OnEvent()方法。

我最初的意思是發布這個評論,但它變得太長了。

首先,你的線程結構對我來說有點混亂,就像你描述的那樣。 Debug.WriteLine("OnEvent:" + Thread.CurrentThread.ManagedThreadId)放在OnEvent ,讓我們知道您從調試輸出中看到的所有線程ID。

也就是說,規則是:

  • 您應該在STA線程上創建WinForms的Timer對象,並且線程應該在啟動之前配置為STA。

  • 此線程可能是也可能不是主UI線程(創建主表單的位置),但仍應執行消息循環(使用Application.Run )以觸發計時器事件。 還有其他方法可以提取消息,但通常不會從.NET代碼中控制它們。

  • 您應該在WinForms的Timer創建的同一個線程上處理源代碼。 然后,您可以根據需要將這些事件“轉發”到另一個線程上下文(使用SynchronizationContext SendPost ),但我無法想到這種復雜性的任何原因。

在我看來,@ Maarten的答案實際上表明了正確的做法。

winforms計時器是一個控件,必須通過將其放在表單上來使用。 你永遠不會把它添加到控件集合中,所以我不希望它能正常工作。 文檔說明如下

實現以用戶定義的間隔引發事件的計時器。 此計時器已針對Windows窗體應用程序進行了優化,必須在窗口中使用。

因此,我建議您使用System.Timers.Timer類的實例。 這個類可以在任何地方使用。

請注意,上面使用的Tick事件由System.Timer.Timer類中的另一個名稱調用,即Elapsed-event

我還不明白為什么Forms.Timer沒有按預期運行,但下面的優秀文章詳細解釋了如何將工作編組到UI線程: http//www.codeproject.com/Articles/31971/Understanding-的SynchronizationContext-部分-I

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM