2016-07-26 40 views
0

我想僅在需要顯示氣球提示時顯示系統任務欄圖標,然後在氣球提示關閉時隱藏圖標。使用計時器時未啓動事件處理程序

然而,一旦顯示的圖標,我不能讓它消失,因爲事件處理函數不是解僱:從由定時器觸發的方法

public partial class MainWindow : Window { 

    public static NotifyIcon trayIcon = new NotifyIcon(); 

    public MainWindow() { 
     InitializeTrayIcon(); 
    } 

    void InitializeTrayIcon() { 
     trayIcon.Text = "My App"; 
     trayIcon.Icon = MyApp.Properties.Resources.myIcon; 
     trayIcon.Visible = false; 

     //the following never gets fired: 
     trayIcon.BalloonTipClosed += (sender, e) => { 
      trayIcon.Visible = false; 
     }; 
     } 

     public static void ShowTrayNotification(ToolTipIcon icon, string title, string text, int duration) { 
      trayIcon.Visible = true; 
      trayIcon.ShowBalloonTip(duration, title, text, icon); 
     } 
} 

ShowTrayNotification()被稱爲:

public abstract class Watcher { 

    protected System.Timers.Timer myTimer = new System.Timers.Timer(1000); 

    //the following is called in a subclass of Watcher, which is instantiated in MainWindow 
    protected void SetupMyTimer() { 
     myTimer.AutoReset = true; 
     myTimer.Elapsed += myTimer_Elapsed; 
     myTimer.Start(); 
    } 

    protected virtual void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { 
     myTimer.Enabled = false; 
     MyTimerElapsedCallback(); 
     myTimer.Enabled = true; 
    } 

    void MyTimerElapsedCallback() { 
     MainWindow.ShowTrayNotification(ToolTipIcon.Info, "Hello There!", "Balloon text here.", 5000); 
    } 
} 

因此顯示氣球。但BalloonTipClosedMainWindow從未被解僱。

我曾嘗試:

  • 把(1)創建NotifyIcon的,(2)氣球的顯示,和(3)MainWindow設置BalloonTipClosed一切,它工作正常(即BalloonTipClosed是燒製)

  • 推杆(1),(2)和(3)在SetupMyTimer()並能正常工作以及

  • 推杆(1),(2)和(3)在MyTimerElapsedCallback()而不是工作(即, BalloonTipClosed沒有解僱)

  • 改變BalloonTipClosedBalloonTipClicked和它工作爲好。

  • 使用非lambda BalloonTipClosed EventHandler,不是工作。

這一點,我想這個問題已經通過定時器做的,但我不知道它是如何影響事件處理,也不怎麼解決。

任何想法?

+0

你在你的MainWindow中調用SetUpMyTimer嗎? – apomene

+0

@apomene不直接。在MainWindow中,我創建了一個新的WatcherSubclass,它最終調用SetupMyTimer()' – Obay

回答

2

您的代碼中存在線程錯誤,計時器的Elapsed事件在線程池線程上引發。當你做這種事情時,你通常會得到一個InvalidOperationException,但是這個檢查並沒有爲NotifyIcon實現。

使其在錯誤線程中可見的副作用是在該線程上創建了一個用於接收事件通知的其他隱藏窗口。它根本不能接收任何通知,線程池線程不會抽取消息循環。糟糕的診斷,沒有例外,也沒有什麼好的方法來看它爲什麼會出錯。

您的ShowTrayNotification()方法必須使用窗體的BeginInvoke()方法,以便代碼在UI線程上運行。由於該方法是靜態的,因此您可以使用Application.OpenForms [0] .BeginInvoke()進行絕對捏合,這使得難度更大。但是讓Watcher類引發事件而不是直接調用表單的方法肯定會更好。或者考慮使用一個簡單的Winforms'定時器,您可以在工具箱中找到它。發佈後,Watcher類沒有可見的附加值。

+0

我通過在MainWindow中創建一個Dispatcher dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher來解決這個問題,並封裝了創建,在Dispatcher.Invoke(new Action(()=> {...}));'ShowTrayNotification()'內部顯示和隱藏'NotifyIcon'。謝謝! – Obay

+0

哦,對,WPF。當您可以使用BeginInvoke()時,切勿使用Invoke()。 –

相關問題