使用WinForms查看详细信息的单独UI线程

使用WinForms查看详细信息的单独UI线程,winforms,multithreading,user-interface,Winforms,Multithreading,User Interface,我们的应用程序的主/详细视图使用datagridview作为主视图,使用自定义控件作为详细视图。“详细信息”视图的计算和渲染需要很长时间,这使得主视图的上/下光标速度非常慢 因此,我们希望details视图能够异步运行(在一个单独的UI线程中),并带有来自主机的更改通知 在单独的线程中创建表单相对简单,因为Application.Run使用表单参数 有没有办法在单独的线程上运行winforms控件?我知道不同线程中的本机窗口可以有父/子关系,只是不知道如何使用winforms设置 TIA,如果在

我们的应用程序的主/详细视图使用datagridview作为主视图,使用自定义控件作为详细视图。“详细信息”视图的计算和渲染需要很长时间,这使得主视图的上/下光标速度非常慢

因此,我们希望details视图能够异步运行(在一个单独的UI线程中),并带有来自主机的更改通知

在单独的线程中创建表单相对简单,因为Application.Run使用表单参数

有没有办法在单独的线程上运行winforms控件?我知道不同线程中的本机窗口可以有父/子关系,只是不知道如何使用winforms设置


TIA,

如果在代码中启动细节视图的更新,则可以通过在用户选择主记录和更新细节视图之间休眠500毫秒来极大地提高可用性


这给用户1/2秒的时间滚动到下一条记录,而无需更新详细信息视图。

从辅助线程更新UI


直觉上,您还应该能够通过使用BackgroundWorker来完成同样的事情。BackgroundWorker设计用于在后台执行内容时更新UI内容,如进度条,并且可以在其操作过程中取消它。

是数据加载导致的速度减慢,还是UI本身的填充造成的


大多数情况下都是前者,因此如果是这样,那么进行数据加载的逻辑应该被抽象到不同的线程中。UI代码可以存在于主线程中,因为更新很快。在这种情况下,您可以使用
线程
后台工作人员
。关键是要将数据加载与GUI群体分开。

< P>如果在渲染过程中遇到速度命中,则应考虑暂停布局直到窗体完成更新,然后在最后刷新一次可见的显示。

this.SuspendLayout();

// Do control stuff here

this.ResumeLayout();
如果没有帮助,请尝试以下方法:

[DllImport("user32.dll")]

public static extern bool LockWindowUpdate(IntPtr hWndLock);
//
LockWindowUpdate(this.Handle);

// Do control stuff here

this.Refresh(); //Forces a synchronous redraw of all controls

LockWindowUpdate(IntPtr.Zero);

实际上,我们确实有这样的延迟(并且很可能应该在原始问题中提到,谢谢。)但是,当详细信息视图开始更新时,它会明显阻止用户的滚动,这就是为什么我们需要在单独的线程中执行此操作的原因。有什么方法可以做到这一点吗?请参阅我关于线程的另一个答案。如果用户在延迟期间滚动,则需要重新启动计时器。不幸的是,不是。实际的UI需要位于不同的线程中,因为计算和渲染调用不同的Winforms控件,而这些控件只能在其UI线程上调用(这是Winforms限制)为了安全地调用它们,我们需要将InvokeSync执行回主线程,这同样意味着阻塞ui。假设我们已经尽可能地使用单个UI线程,那么最初的问题仍然是:有没有一种方法可以在不同的UI线程上设置winforms控件?在我们的例子中,它无疑是更新和重新计算视图。数据已在内存中。布局和绘图算法是CPU密集型的。此外(如下面的另一条评论所述),这些算法需要调用winforms子控件,而这些子控件只能在其UI线程上调用。布局和绘图是独立的,可能是分离的。如果您可以提供有关视图中发生的情况的更多详细信息(请编辑您的原始问题),我们可能可以为您提供有关该问题的更具体的帮助。与其追求一个完全不同的过程,不如将其引导回原始问题-winforms控件是否可以在单独的ui线程上运行?我们感谢大家的建议,但到目前为止还没有人直接解决这个问题,这个问题是独立于应用程序的,纯粹是关于框架的。这是一个好问题,但我认为,你在这里寻找的答案很有可能只是绕过了真正的问题。我们已经这样做了:)为了让你了解这个问题的范围,我们已经在这方面努力了几个月,取得了最大的绩效。是的,我们使用了延迟更新、backgroundworker、将所有数据保留在内存中以及SuspendLayout()。我们尽可能多地记忆计算。我们将重绘区域与当前图形上下文相交。我们已经到了需要使用单独线程进行控制的地步。再说一遍,有没有办法做到这一点?我还没有找到,但我会继续寻找。问题在于Winforms使用的消息泵本质上是从Windows事件模型继承的单线程单元(STA)。即使在WPF(支持一些多线程屏幕更新)中,消息泵仍然是STA。我认为唯一可以做的就是找到一种方法,在用户移动到另一个记录时以某种方式中止屏幕更新(因为该用户操作实际上会使正在完成的任何屏幕更新无效)。好的,这里还有一点信息:。它描述了如何同时运行两个消息泵。也许这会对你有所帮助。不过,我不能保证,如果你尝试它,它不会杀死一只小猫。谢谢,但是我们知道——上面的原始问题提到,在单独的UI线程中运行第二个表单是直接的。我们正在寻找一种在单独的UI线程中运行控件的方法。Run接受窗体参数,而不是控件。