【问题标题】:Display form without blocking execution of program在不阻塞程序执行的情况下显示表单
【发布时间】:2017-10-09 16:36:11
【问题描述】:

我试图从我的 DLL 的函数中显示一个简单的表单(仅显示一个标签)。但是,我需要在不阻止执行此功能的情况下显示此表单(例如,显示表单并继续执行功能。)

我试过只使用:

form.ShowDialog();

然而,这显然是一个模态对话框,因此会阻止执行,直到用户与之交互。我也试过使用:

form.Show();

但这会导致表单在所有其他窗口后面加载,并且控件无法正确加载(仅在应有的位置显示空白框。)

为了尝试解决这些问题,我尝试在新线程上创建和显示表单,如下所示:

Thread thread = new Thread(ShowXForm);
thread.Start();

像这样:

new Thread(delegate ()
{
    ShowXForm();
}).Start();

地点:

private void ShowXForm()
{
    frmX XForm = new frmX();
    XForm.ShowDialog();
}

同样,这些导致的行为与仅使用 Show 而不创建新线程几乎相同。

在不同线程上运行的另一个困难是我仍然需要能够从主线程更新表单上的标签(可以使用委托来实现吗?)

我知道将主线程作为 UI 线程是一种很好的做法,但是由于这是一个 DLL 而不是 Windows 窗体应用程序,所以感觉 UI 可能不应该在主线程上运行。

【问题讨论】:

  • 你能说明你的 DLL 中的函数是如何被调用的吗?您是从 .Net Windows 窗体应用程序中调用它吗?
  • 在看到另一个问题的完全相反后,我不得不说:这表明您付出了巨大的努力。我的第一个想法是“单独的线程”,但后来我看到你已经尝试过了。我希望我能给你一个更好的答案。
  • 我在问你是怎么称呼它的,因为我记得你前几天问的一个 COM 暴露的 C# dll,我想知道这是否是一个相关问题。您是否尝试通过 COM 调用调用此方法?
  • 使用那个单独的线程,您是否尝试过显示表单 (XForm.Show()),告诉表单到顶部(加载时执行类似 this.BringToFront() 的操作),并在其上设置计时器那会关闭它(如果它是您只想暂时显示的消息)?
  • @pstrjds 它与我前几天询问的同一个项目有关,但这个函数不是直接通过 COM 调用的。我不确定这会如何影响我想要实现的目标?

标签: c# .net visual-studio dll


【解决方案1】:

对 Application.Run() 的调用需要INSIDE一个新线程。

类似...

private void ShowXForm()
{    
    new Thread(delegate ()
    {
        frmX XForm = new frmX();
        Application.Run(XForm);
    }).Start();
}

但是,如果您想让它更新,您必须在类级别保留该表单引用,并为其提供一种传递更新的机制,并让该表单使用委托/Invoke( )。

【讨论】:

  • 我开始添加这种性质的建议答案,但我认为您需要做的一件事是将该线程上的 ApartmentState 设置为 STA。所以你需要将创建和开始调用分开,这样你就可以将其设置为 STA。
  • 我刚刚也使用了 ApartmentState 集尝试了这段代码(正如@pstrjds 所建议的那样)。 private void ShowNotificationsForm() { Thread thread = new Thread(delegate () { frmNotifications notificationsForm = new frmNotifications(); Application.Run(notificationsForm); }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); 但是,这仍然没有任何不同。也许我在这里遗漏了什么?
  • 一个有趣的观察是,在后面的代码中遇到 thread.sleep 之前,似乎甚至没有创建表单?
  • @tj_ush - 在我看来,当时还有很多其他事情正在发生,如果不了解您正在做的更多事情,我们可能很难诊断/提出建议。比如,你说的Thread.Sleep在哪里?您的代码如何连接到主代码?您是否只是实现了一个接口,而您的 dll 是在运行时注入的?
  • @pst 抱歉,我只发布了我认为与问题相关的代码。好的,让我们快速浏览一下代码。正如你所说,这只是一个接口,DLL 是在运行时注入的。有一个通过 COM 调用的函数(函数 A)——它执行几个步骤,包括调用问题所指的函数 (X)。函数 X 发出许多 HTTP 请求,这些请求的结果应显示在表单中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-19
  • 1970-01-01
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-05
相关资源
最近更新 更多