【问题标题】:Can I go back to the thread execution context?我可以回到线程执行上下文吗?
【发布时间】:2014-01-28 11:24:38
【问题描述】:

我需要在另一个线程上创建一个表单,就像应用程序启动时的启动屏幕一样。

LoadingMyForm w = null;
Thread thread = new Thread(() =>
{
    try
    {
        w = new LoadingMyForm();
        w.Show();

        System.Windows.Threading.Dispatcher.Run();
    }
    catch (Exception ex)
    {
        w.Close();
        w = null;
    }
});

thread.SetApartmentState(ApartmentState.STA);
thread.Start();

这暂时有效,但要停止它,我必须调用thread.Abort();,这将引发异常,当我捕获该异常时,如您所见,我关闭窗口。是否有某种机制可以返回线程执行上下文并在表单上调用Close 方法?

据我了解:

System.Windows.Threading.Dispatcher.Run();

使我的线程保持活动状态,因此至少可以分配其他操作在该线程上运行吗?

【问题讨论】:

    标签: c# .net wpf multithreading user-interface


    【解决方案1】:

    只需使用表单的Dispatcher 即可完成工作。最简单的调用是这样做:

    w.Dispatcher.Invoke(w.Close);
    

    ...尽管您可能希望向 LoadingMyForm 类添加一个包装逻辑的方法:

    public void ThreadSafeClose()
    {
        Dispatcher.Invoke(Close);
    }
    

    您应该注意,虽然这会安全地关闭窗口,但它会使 ThreadDispatcher 仍在运行 - 您可能想要手动关闭它们,但 iut 从您的问题中听起来您想要重新无论如何稍后使用线程。同样,Dispatcher.InvokeDispatcher.BeginInvoke 方法将在这里为您提供帮助。

    【讨论】:

      【解决方案2】:

      下面是另一种方法。用法:

      var splash = new SplashWindow();
      
      // continue when the window is shown
      splash.Start(() => new LoadingMyForm());
      
      // do some initialization work
      // ...
      
      splash.Stop();
      

      实施:

      class SplashWindow
      {
          CancellationTokenSource _cts;
          Thread _thread;
      
          // show window
          public void Start(Func<Window> createWindow)
          {
              var tcs = new TaskCompletionSource<bool>(false);
              _cts = new CancellationTokenSource();
              var token = _cts.Token;
      
              _thread = new Thread(() =>
              {
                  var window = createWindow();
                  window.Loaded += (s, e) =>
                  {
                      // window is shown
                      tcs.SetResult(true);
                  };
      
                  var dispather = Dispatcher.CurrentDispatcher;
                  dispather.InvokeAsync(() =>
                      window.Show());
      
                  using (token.Register(() =>
                      dispather.BeginInvokeShutdown(DispatcherPriority.Normal),
                      useSynchronizationContext: false))
                  {
                      Dispatcher.Run();
                  }
      
                  window.Close();
              });
      
              _thread.IsBackground = true;
              _thread.SetApartmentState(ApartmentState.STA);
              _thread.Start();
              tcs.Task.Wait();
          }
      
          // hide window
          public void Stop()
          {
              _cts.Cancel();
              _thread.Join();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-27
        • 1970-01-01
        • 1970-01-01
        • 2010-10-06
        • 1970-01-01
        • 1970-01-01
        • 2011-03-13
        • 1970-01-01
        相关资源
        最近更新 更多