如何避免从工作线程到 GUI 线程的主体传播

Posted

技术标签:

【中文标题】如何避免从工作线程到 GUI 线程的主体传播【英文标题】:How to avoid principal propagation from worker-thread to GUI-thread 【发布时间】:2015-07-31 20:36:39 【问题描述】:

我们有一个带有工作线程的 Windows 应用程序,需要更新 GUI。我们使用 BeginInvoke 异步执行此操作。我们的问题,在下面的示例中演示,是 Principal 被传播到我们想要避免的 GUI 线程,因为在我们的实际应用程序中,我们执行的服务器请求由于错误的身份而失败。有没有办法避免这种传播?

  private Thread _thread;

  public Form1()
  
     InitializeComponent();

     Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("MainUser"), new[]  "User" );

     _thread = new Thread(ThreadProc);
     _thread.Start(this);
  

  private void ThreadProc(object parameter)
  
     Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("ThreadUser"), new[]  "User" );

     var form = parameter as Form1;

     while (true)
     
        form.BeginInvoke(new Action(() => ShowIdentity()));
        Thread.Sleep(4000);
     
  

  private void ShowIdentity()
  
     lblIdentity.Text = Thread.CurrentPrincipal.Identity.Name;
  

【问题讨论】:

【参考方案1】:

有关在 .NET 中模拟 Windows 用户的说明,请参阅 http://blogs.msdn.com/b/shawnfa/archive/2005/03/22/400749.aspx。也就是说,如果您在客户端计算机上执行此操作,则需要在 UI 用户的帐户下访问目标帐户的密码,这可能是您不想要的。为了防止这种情况,您需要使 UI 用户可以访问服务器端服务,或者使用中间服务(例如:客户端计算机上的服务器托管或 Windows 服务)在运行时代理对服务器端服务的调用有权访问目标服务的帐户。

【讨论】:

如果我做对了,这解决了错误用户调用服务器的问题,而不是如何防止工作线程在 GUI 线程上设置主体的问题。但这仍然是一个解决方案,谢谢。【参考方案2】:

所以我想您在标签上打印了名称“MainUser”?

发生的事情不是主线程的 Thread.Principal 主体正在传播到另一个线程,而是ShowIdentity 正在同一个线程(主线程)上完成!

InvokeBeginInvoke 将要在创建控件的线程上完成的工作排队(或者正如 MSDN 所说的“在创建控件的底层句柄的线程上异步执行指定的委托” )。

这两种方法的区别在于Invoke 将阻塞直到工作项完成线程,而BeginInvoke 只将工作项添加到队列中并立即返回。

因此,在您的示例中,您每 4 秒从您创建的线程开始向此队列添加一个 Action。因为 UI 线程不忙于做其他事情,它会在排队后很快处理这项工作 - 但它将在 UI 线程上运行(其关联的主体名为“MainUser”)。

这有意义吗?

【讨论】:

以上是关于如何避免从工作线程到 GUI 线程的主体传播的主要内容,如果未能解决你的问题,请参考以下文章

如何在 GUI 线程和工作线程之间共享数据?

如何从另一个线程更新 GUI?

如何从另一个线程更新 GUI?

如何从另一个线程更新 GUI?

向工作线程PyQt发送值?

如何从 non_GUI 类和我们可以在主 GUI 类中检测到的非 GUI 线程发出信号