Come eseguire il codice nel Thread della GUI?

Ho un FileSystemWatcher che reagiscono ai cambiamenti del caso.

Voglio aprire il file, leggere la visualizzazione del contenuto in una textbox e nascondere il pop-up che è stato creato dopo 1 sec. Il codice quasi un lavoro, ma qualcosa di non riuscire quando si nasconde il popup.

Ecco un frammento di codice :

       txtLog.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() {
            this.txtLog.Text = dataToDisplay;
            extendedNotifyIcon_OnShowWindow();
            Thread threadToClosePopup = new Thread(new ThreadStart((Action)delegate() { 
                Thread.Sleep(1000); 

                extendedNotifyIcon_OnHideWindow();
       }));
            threadToClosePopup.Start();
        });

Come si può vedere, io uso la Invocare per impostare il testo in quanto l’evento è in un altro thread (FileSystemWatcher). Ma per nascondere le finestre la extendedNotifyIcon_OnHideWindow() non viene eseguito nel thread dell’interfaccia grafica. Come posso eseguire nel thread della GUI?

OriginaleL’autore Patrick Desjardins | 2010-09-15

6 Replies
  1. 10

    Per eseguire il extendedNotifyIcon_OnHideWindow metodo sul thread della GUI utilizzare il Dispatcher come avete fatto per la mostra.

    Thread threadToClosePopup = new Thread(new ThreadStart((Action)delegate() { 
      Thread.Sleep(1000); 
      txtLog.Dispatcher.Invoke(
        DispatcherPriority.Normal,
        (Action)() => extendedNotifyIcon_OnHideWindow());
    }));

    OriginaleL’autore JaredPar

  2. 16

    Questo funziona bene per WPF con MVVM.

    Application.Current.Dispatcher.Invoke(
        () =>
        {
             //Code to run on the GUI thread.
        });

    Questo non lavoro in modo coerente (avrà esito negativo se siamo all’interno di un gestore per Reattiva Estensioni):

    Dispatcher.CurrentDispatcher.Invoke(
        () =>
        {
             //Fails if we are inside a handler for Reactive Extensions!
        });

    Extra per gli Esperti: Il Motivo?

    Dal progetto, qualsiasi thread può avere un dispatcher thread associato, vedere MSDN: Classe Dispatcher.

    Se facciamo riferimento a Dispatcher.CurrentDispatcher da qualsiasi thread, possa effettivamente creare un nuovo thread del dispatcher, che è separato ufficiale WPF UI dispatcher thread. Quando si tenta di eseguire il codice appena creato dispatcher thread, WPF buttare in quanto non è ufficiale UI dispatcher thread.

    La soluzione è di usare sempre Application.Current.Dispatcher.Invoke(), o Application.Current.Dispatcher.BeginInvoke(). Vedere Qual è la differenza tra Invoke() e BeginInvoke().


    Testato su:

    • WPF
    • .NET 4.5
    • .NET 4.6
    • .NET 4.61
    Hai salvato la mia giornata!
    Sei il benvenuto. Aggiornato questo post per aggiungere il motivo per cui questo si verifica.

    OriginaleL’autore Contango

  3. 2

    Questo vi darà la Finestra dispatcher:

    Dispatcher.CurrentDispatcher

    Come lungo come si ottiene il thread di windows.

    Per ottenere da un altro thread Applicazione da provare.Corrente.Dispatcher.Invoke(new Azione(() => {metodo()}));

    OriginaleL’autore ozczecho

  4. 2

    Controllo.Richiamare

       txtLog.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() {
            this.txtLog.Text = dataToDisplay;
            extendedNotifyIcon_OnShowWindow();
            Thread threadToClosePopup = new Thread(new ThreadStart((Action)delegate() { 
                Thread.Sleep(1000); 
    
                extendedNotifyIcon.Invoke(extendedNotifyIcon_OnHideWindow);
       }));
            threadToClosePopup.Start();
        });

    OriginaleL’autore Alex Reitbort

  5. 1

    Basta avvolgere extendedNotifyIcon_OnHideWindow(); in un Dispatcher.Invoke()

    Ma preferisco farlo (tutti im XAML) con un’Animazione e con un EvenTrigger che innesca sulla TimeLine.Evento compiuto.

    Io sono di veramente nuovo per WPF, solo bisogno di modificare un codice esistente. Il codice XAML popup e, infatti, pop giù quando il mouse lascia il contenitore. Ma, ora ho bisogno di aggiungere qualcosa di pop, dal codice e pop giù dal codice, senza cancellare l’iniziale comportamento. +1 per l’idea

    OriginaleL’autore bitbonk

  6. 0

    Il problema è che extendedNotifyIcon_OnHideWindow viene eseguito su un thread diverso il thread dell’interfaccia utente. Sarà necessario utilizzare il Dispatcher per quella parte. Inoltre, non vorrei creare un thread dedicato solo attendere un secondo. Si può facilmente effettuare il refactoring, a parte un System.Threading.Timer. Qui è il mio refactoring versione.

    txtLog.Dispatcher.Invoke(
        (Action)(() =>
            {
                txtLog.Text = dataToDisplay;
                extendedNotifyIcon_OnShowWindow(); 
                new Timer(
                    (state) =>
                    {
                        button1.Dispatcher.BeginInvoke(
                            (Action)(() =>
                                {
                                  extendedNotifyIcon_OnHideWindow(); 
                                }), null);
                    }, null, 1000, Timeout.Infinite);
            }));

    OriginaleL’autore Brian Gideon

Lascia un commento