代码之家  ›  专栏  ›  技术社区  ›  Patrick Desjardins

如何在GUI线程中执行代码?

  •  5
  • Patrick Desjardins  · 技术社区  · 14 年前

    我有一个FileSystemWatcher,可以对更改的事件做出反应。

    以下是代码片段:

           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();
            });
    

    如您所见,我使用Invoke来设置文本,因为事件位于不同的线程(FileSystemWatcher)中。但是为了隐藏窗口,扩展的NotifyIcon_OnHideWindow()不会在GUI的线程中执行。如何在GUI线程中执行它?

    6 回复  |  直到 14 年前
        1
  •  11
  •   JaredPar    14 年前

    执行 extendedNotifyIcon_OnHideWindow 方法使用 Dispatcher 就像你展示的那样。

    Thread threadToClosePopup = new Thread(new ThreadStart((Action)delegate() { 
      Thread.Sleep(1000); 
      txtLog.Dispatcher.Invoke(
        DispatcherPriority.Normal,
        (Action)() => extendedNotifyIcon_OnHideWindow());
    }));
    
        2
  •  25
  •   Contango    4 年前

    WPF 具有 MVVM .

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

    这将 始终如一地工作(如果我们在反应式扩展的处理程序中,它将失败):

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

    专家加分:原因何在?

    MSDN: Dispatcher Class

    如果我们参考 Dispatcher.CurrentDispatcher

    Application.Current.Dispatcher.Invoke() ,或 Application.Current.Dispatcher.BeginInvoke() What's the difference between Invoke() and BeginInvoke()


    更新2020-05-02:可以使用多个wpfui调度程序线程运行WPF应用程序。我和一个巨大的WPF应用程序一起工作。很难让它工作,但一旦它工作-这是惊人的,整个应用程序运行速度快了一个数量级,因为有多个UI调度线程。很高兴回答这个问题。


    测试日期:

    • .NET 4.5
    • .NET 4.6
    • .NET 4.61
        3
  •  3
  •   ozczecho    14 年前

    这将为您提供窗口调度程序:

    Dispatcher.CurrentDispatcher
    

        4
  •  2
  •   Alex Reitbort    14 年前

       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();
        });
    
        5
  •  1
  •   bitbonk    14 年前

    包起来就行了 extendedNotifyIcon_OnHideWindow(); 变成一个 Dispatcher.Invoke()

    但是我更愿意使用动画和事件触发程序来完成(所有的imxaml)时间线。已完成事件。

        6
  •  0
  •   Brian Gideon    14 年前

    extendedNotifyIcon_OnHideWindow 正在UI线程以外的线程上执行。你需要使用 Dispatcher System.Threading.Timer . 这是我的重构版本。

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