Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 遗留应用程序在非ui线程中创建对话框_C#_Multithreading - Fatal编程技术网

C# 遗留应用程序在非ui线程中创建对话框

C# 遗留应用程序在非ui线程中创建对话框,c#,multithreading,C#,Multithreading,我在一个遗留应用程序上工作了一段时间,发现了一点问题。该系统是一个极其复杂的客户机/服务器,具有标准和自定义框架 应用程序中内置的自定义框架之一涉及验证工作流操作。它发现潜在的错误,将它们分为警告和错误,并将结果传递回客户端。警告和错误之间的主要区别在于警告询问用户是否希望忽略错误 我遇到的问题是,此提示符的对话框是在非ui线程上创建的,因此,当显示该对话框时,我们会遇到跨线程问题。我试图调用对话框的显示,但是由于尚未创建窗口句柄,因此失败。(InvokeRequired返回false,我认为在

我在一个遗留应用程序上工作了一段时间,发现了一点问题。该系统是一个极其复杂的客户机/服务器,具有标准和自定义框架

应用程序中内置的自定义框架之一涉及验证工作流操作。它发现潜在的错误,将它们分为警告和错误,并将结果传递回客户端。警告和错误之间的主要区别在于警告询问用户是否希望忽略错误

我遇到的问题是,此提示符的对话框是在非ui线程上创建的,因此,当显示该对话框时,我们会遇到跨线程问题。我试图调用对话框的显示,但是由于尚未创建窗口句柄,因此失败。(InvokeRequired返回false,我认为在本例中这意味着它在父树中找不到合适的句柄,而不是它不需要它。)


有人对我如何创建此对话框并让UI线程设置并调用它有什么建议吗?

我不完全清楚实现的细节,但下面的代码是如何处理从非UI线程到UI线程的调用。此代码段假定“This”对象是windows窗体,表示ui线程

其思想是,非ui线程调用名为“ShowMessageBox”的方法,该方法位于ui线程上。当调用发生时,请检查ui线程上的对象所需的this.invokererequired,在本例中,该对象是windows窗体。invokererequired将返回“true”,这将导致执行if语句第一部分中的代码。此代码通过创建与“ShowMessageBox”方法具有相同签名的委托并重新传递发送方对象和事件参数,从主ui线程调用ShowMessageBox函数,实际上将非ui线程调用编组到ui线程。随后对“ShowMessageBox”方法的调用现在被“封送”到ui线程,并将绕过if的第一部分,移动到else,在那里您可以调用messagebox或表单或任何您需要的东西

享受吧

private object _lock = new object(); //should have class scope

private void ShowMessageBox(object sender, EventArgs e)
{
  if (this.InvokeRequired)
  {
    lock (_lock)
    {
      EventHandler d = new EventHandler(ShowMessageBox);
      this.Invoke(d, new object[] { sender, e });
      return;
    }
  }
  else
  {
    MessageBox.Show("Show some messsage or invoke your form instance.");
  }
}

在创建控件之后。通过访问其句柄属性强制创建句柄:

sync = new System.Windows.Forms.Control();
var temp = sync.Handle;
然后你就可以调用它了:

sync.Invoke((Action)(() => { }));

正如我前面提到的,在这种情况下,这不起作用。如果没有窗口句柄,则无法调用invoke。您是否考虑过上述模式并创建自定义EventArgs类,该类将传递消息或枚举类型,然后您可以使用该类从if语句的else部分中创建相应的表单实例。这将避免在非ui线程上创建表单的问题。您只需要传递某种类型的指示符或消息,然后从ui线程对该消息执行操作,而不是尝试从创建表单实例的线程以外的线程调用表单实例。这可能值得一试,尽管这相当复杂。代码相当可怕。我会再考虑一下的,谢谢。