【问题标题】:Visual Basic 2008 - New Form on a different threadVisual Basic 2008 - 不同线程上的新表单
【发布时间】:2011-06-22 18:22:14
【问题描述】:

我的“form1”只是一个简单的页面,其中的按钮启动不同的表单来完成所有工作,前四个按钮的“form1”代码如下。

我想要的是让每个表单在单独的线程中运行。

Public Class Main
    Private Sub btnDownLoadStockPrices_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDownLoadStockPrices.Click
        LoadStocksFromDownloadSite.Visible = True
    End Sub

    Private Sub btnLoadOptionsIntoDatabase_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoadOptionsIntoDatabase.Click
        LoadOptionsIntoDatabase.Visible = True
    End Sub

    Private Sub btnVerifyDatabases_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnVerifyDatabases.Click
        VerifyDatabase.Visible = True
    End Sub

    Private Sub btnAnalyzeStock_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAnalyzeStock.Click
        AnalyzeSingleStock.visible = True
    End Sub
End Class

我发现了很多代码示例,让单个表单上的不同按钮在单独的线程中运行子例程,但由于某种原因,我似乎无法将其应用于整个表单。

我认为这很简单,就像我需要将每个新线程绑定为每个表单“加载”例程的句柄,但我就是无法让它工作。我根本不关心“同步”线程,因为每个表单都是一个完全不同的功能程序。

任何帮助将不胜感激!

【问题讨论】:

  • 为什么要每个表单在单独的线程中运行?

标签: vb.net winforms multithreading forms


【解决方案1】:

这不是很常见;通常最好将所有 UI 内容限制在单个线程中。但是,如果您确信需要每个表单在单独的线程上运行,则必须考虑 Windows API 事件处理模型。 [over]-简化版本是每个表单必须有自己的message loop 才能从队列中删除事件消息并处理它们,因此如果您想在新线程上打开表单,则需要创建该消息泵。

最简单的方法是使用Application.Run method,并让 .NET Framework 为您处理创建该消息泵。例如:

Dim frm As Form1 = New Form1()
Application.Run(frm)

通过查看您问题中显示的代码,我无法辨别任何这些表单需要在单独线程上运行的可能原因。您可以调用多个表单的Show method,使它们同时显示在屏幕上。只要您不使用ShowDialog method,它们就不会相互阻止,它将每个都显示为模式对话框。这就是许多应用程序同时在屏幕上显示多个工具箱窗口和其他类型的表单的方式。

如果您需要执行某种类型的处理器密集型计算,您仍然不需要在单独的线程上运行每个计算。启动一个后台线程(BackgroundWorker class 使这变得非常简单)并使用Invoke method 更新相应表单的 UI。

【讨论】:

  • 感谢您的帮助...我想要不同线程的原因是某些功能要等到一天中的特定时间才能从我的数据提供者那里下载“日终”股票和期权数据.虽然这些任务正在等待/下载,但我希望能够使用其他形式。我想我可以将这些特定的子例程放在一个新线程上,但我认为每个表单都单独运行会更容易。
  • @David:那我回答的后半部分就是你要找的。绝对没有理由在单独的线程上运行表单,以便它们在不同时间可用。事实上,既然您说您甚至没有尝试在表单之间进行通信,那么您的任务就更容易了。只需创建一个表单类的新实例,然后调用frm.Show()。您可以一次在屏幕上显示任意数量的它们,并分别与它们进行交互。如果您想在后台线程上进行下载,那也很简单。网上有很多BackgroundWorker的例子。
  • 感谢您的快速回复。我认为让我感到困惑的是所有表单都是项目的一部分,它们都会在启动时自动加载,当我单击 Form1 中的按钮时,我只是让它们“可见”。我想我试图找到一种方法让它们仅在我单击按钮时才加载,并在新线程中执行此操作。我将尝试将等待/下载的进程放在 BackgroundWorker 中,看看是否可以同时使用其他表单。
  • @David:为什么所有的表单都会在启动时自动加载?你打算让这种情况发生吗?您知道您可以随时通过代码加载和显示新的表单对象,对吧? Dim frm As Form1 = New Form1() : frm.Show() 只需将类似的内容放入按钮的 Click 事件处理程序方法中即可。目前还不清楚你从哪里得到你需要线程的想法。正如大卫的回答所暗示的那样,线程确实有其目的,但往往只是增加了不必要的复杂性。我认为这是后者的情况。
  • 实际上,我不知道如何防止其他窗体在启动时加载......它们是在 Visual Studio 中使用“项目 - > 添加 Windows 窗体”创建的。我在任何地方都没有任何“新表单”命令,它们只是“在那里”,当我希望它显示时,我将表单的属性设置为“可见”。
【解决方案2】:

您当然可以在 Win32 上执行此操作,但我不知道这在 .net 上的映射情况如何。

关键问题是窗口句柄具有线程亲和性。因此,您确实需要在该线程中与他们进行所有交互。本质上,这意味着您在其线程中创建与该表单关联的所有窗口句柄。您还需要在线程中运行消息循环。

人们通常在主线程之外运行所有 UI 并在单独的线程中处理长时间运行的操作的原因是这样更容易。您应该再次问自己为什么要以这种非标准方式进行操作。

我怀疑您并没有看到全貌。桌面应用程序中对线程的需求主要出现在您有长时间运行的操作时。通常,您希望保持 UI 响应并为长时间运行的操作提供反馈。这样做会导致线程。

但是,在您提出的解决方案中,您现在有大量额外的线程和复杂性,并且您仍然面临最初的问题!除非您在单独的线程中执行该操作,否则您的一个表单上的长时间运行操作将挂起,并且我们再次达到问题的标准解决方案。

【讨论】:

  • 感谢 David - 正如我在对 Cody 的其他回复中所指出的,我不在乎该表单在等待和下载时是否“挂起”,但我想使用与此同时。我从来没有使用过任何类型的多线程,所以我不确定什么是“标准”,什么是“非标准”:-)
  • @David 我仍然认为在主线程之外运行所有 UI 并将长时间运行的计算放在单独的线程中会容易得多。如果您让 UI 线程 挂起 ,那么系统会对此感到有些不耐烦并淡出您的 Window 并威胁要杀死它,因为它没有响应。用于计算的工作线程可能也是更简单且更好的选择。
  • 谢谢,感谢您和 Cody 的指导。我在想将每个表单加载到一个新线程中将是一件简单的事情,这样我就可以在每个表单上编写我想要的任何东西,而不必担心管理其他任何事情。正如 Cody 上面建议的那样,我将研究使用 BackgroundWorker 进行等待/下载/数据库填充 - 这看起来是最好的选择。
猜你喜欢
  • 1970-01-01
  • 2023-03-10
  • 2017-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
相关资源
最近更新 更多