0

私のアプリは、時々バルーン通知を表示する必要があります。私はActionを実行してNotifyIconを作成し、バルーン通知を表示してシステムトレイアイコンを廃棄するDispatcher.Invoke()でこれを行います。Dispatcher.Invokeが呼び出されないことがあります

public abstract class Foo { 
    void Bar() { 
     MainWindow.ShowTrayNotification(ToolTipIcon.Info, "Hello There!", "Balloon text here."); 
    } 
} 

public partial class MainWindow : Window { 

    static Dispatcher dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher; 

    public static void ShowTrayNotification(ToolTipIcon icon, string title, string text) { 
     dispatcher.Invoke(new Action(() => { 
      //anything here is not run 
      UIHelper.ShowTrayNotification(icon, title, text); //static method 
     })); 
     //anything here is also not called if dispatcher.Invoke() is not run 
    } 
} 

ただし、Dispatcher.Invokeが実行されないことがあります。ロギングはその直前で停止し、InvokeActionの内部でロギングは発生しません。

私がPCシャットダウンを起動すると、突然Invokeが起動し(通知が表示され)、正常に処理されます(シャットダウン前のコールバックが実行されます)。

デバッグ> Windows>スレッドを実行しようとしましたが、デバッグモードで問題が発生しないため、UIスレッドがブロックする原因を見つけることができません。

この原因とは何ですか?どのように修正できますか?

UPDATE

私は、次を試してみましたが、彼らは動作しませんでした:

  • 私はBeginInvokeにそれを変更しました。

  • DispatcherPriority.Sendを加えた。

UPDATE 2

public class UIHelper 
{ 
    public static void ShowTrayNotification(ToolTipIcon icon, string title, string text) { 
     NotifyIcon trayIcon = new NotifyIcon(); 
     trayIcon.Icon = MyApp.Properties.Resources.myIcon; 
     trayIcon.Text = "MyApp"; 
     trayIcon.BalloonTipClosed += TrayNotificationClosed; 
     trayIcon.Visible = true; 
     trayIcon.ShowBalloonTip(5000, title, text, icon); 
    } 

    static void TrayNotificationClosed(object sender, EventArgs e) { 
     ((NotifyIcon)sender).Visible = false; 
     ((NotifyIcon)sender).Icon = null; 
     ((NotifyIcon)sender).Dispose(); 
     sender = null; 
    } 
} 
+1

方法を参照してください? 'UIHelper.Dispatcher.Invoke ... 'のようにするか、ディスパッチャの前に' MessageBox'を置いてみてください.Invokeメソッドが実行されているかどうか確認してください。それは単なる提案です。 –

+0

アプリのUIスレッドが別のもので占有されていると、Dispatcher.Invoke()がデッドロックします。 Debug> WIndows> Threadsデバッガーウィンドウを使用して診断します。 –

+0

@JakubLokša 'dispatcher.Invoke'は決して動かない。 'MainWindow'のディスパッチャを使用して、' UIHelper'の 'NotifyIcon'がメインのUIスレッドで作成されていることを確認します。そうでなければ、表示されません。 – Obay

答えて

0

このようにそれを試してみてください。

public partial class MainWindow : Window 
    { 

     static Dispatcher dispatcher = System.Windows.Application.Current.Dispatcher; 

     public static void ShowTrayNotification(ToolTipIcon icon, string title, string text) 
     { 
      if (dispatcher != null && !dispatcher.CheckAccess()) 
      { 
       dispatcher.Invoke(() => ShowTrayNotification(icon, title, text)); 
       return; 
      } 
      UIHelper.ShowTrayNotification(icon, title, text); 

     } 
    } 

また、オブジェクト自体にディスパッチャーを呼び出すことについてDispatcher.CurrentDispatcher vs. Application.Current.Dispatcher

+0

有望に見えますが、初めてCheckAccessを聞いたことがあります。なぜそれが必要ですか?docsは、 '呼び出し元のスレッドがこのDispatcherに関連付けられたスレッドであるかどうかを判定します。呼び出し元のスレッドを 'System.Windows.Application.Current.Dispatcher'に関連するスレッドにしたくないのはなぜですか?そしてなぜ 'ShowTrayNotification'はその場合に自分自身を呼び出すべきですか? – Obay

+0

メソッドは、コールが指定されたディスパッチャからすでに来ているかどうかをチェックします。ディスパッチャーがまだUI上で実行されていない場合は、そのメソッドを呼び出すだけです。 – KroaX

+0

UIスレッドで実行する必要はありませんか?私は前に 'Dispatcher.Invoke'を使っていなかったので、通知は表示されませんでした。 – Obay

関連する問題