处理“大量”数据时的 WinForms UI 响应能力

2023-11-29

我正在修改一个 Windows 窗体,以允许在后台加载数据,同时 UI 保持响应。数据的检索和绑定都需要相当长的时间。理想情况下,我会在后台执行这两项操作,但是对于我应该在后台执行哪种 UI 更新(如在主线程之外)存在一些模糊性。一个在后台显示数据检索和数据绑定的可靠示例将非常有帮助。


检索可以而且应该被推送到后台线程 - 但有一些模式可以将其全部到位。

基本上,您将启动一个后台线程来检索数据,一旦完成,它将需要合并回 UI 线程以执行实际的 UI 更新(跨线程的 UI 更新非常糟糕)。

后台线程的三种基本方式供您探索

  • 最简单/最有限(并且在我看来很奇怪)的是BackgroundWorker组件
  • 使用委托及其 BeginInvoke()/EndInvoke() 方法提供了易用性和灵活性的良好平衡(并使用 ThreadPool 线程)
  • 使用原始 Thread 对象提供了最多的控制,但设置速度比 ThreadPool Threads 慢

就我个人而言,我倾向于“代表”选项;一旦你掌握了模式,它们就很容易使用。从前面看,BackgroundWorker 看起来不错,但有一些问题和缺失的管道,使其使用起来比您想象的更加麻烦。让我快速制作一个委托方法的简短示例;我会尽快更新...

edit

这里有一些代码,它是用 VB 编写的,但如果您是 C# 人员,应该很容易转录。关于后台线程的行为方式,您还有更多选择,因此这里有两个示例。非阻塞是我的首选,但如果您将其安装到现有代码中,那么阻塞可能对您来说更容易。

非阻塞,一旦后台线程完成,将在 UI 线程上调用回调方法 (GetData_Complete)

Sub Main()

    Console.WriteLine("On the main thread")
    Dim dataDelegate As New GetDataCaller(AddressOf GetData)

    Dim iar As IAsyncResult

    ' Non-blocking approach using a callback method
    iar = dataDelegate.BeginInvoke(AddressOf GetData_Complete, Nothing)

End Sub

Private Delegate Sub GetData_CompleteCaller(ByVal iar As IAsyncResult)
Private Sub GetData_Complete(ByVal iar As IAsyncResult)
    If InvokeRequired Then
        Dim invokeDelegate As New GetData_CompleteCaller(AddressOf GetData_Complete)
        Invoke(invokeDelegate, New Object() {iar})
        Exit Sub
    End If

    ' Downcast the IAsyncResult to an AsyncResult -- it's safe and provides extra methods
    Dim ar As System.Runtime.Remoting.Messaging.AsyncResult = DirectCast(iar, System.Runtime.Remoting.Messaging.AsyncResult)

    Dim dataDelegate As GetDataCaller = DirectCast(ar.AsyncDelegate, GetDataCaller)
    Dim result As String = dataDelegate.EndInvoke(iar)

    Console.WriteLine("On the main thread again, background result is: " + result)

End Sub

Private Delegate Function GetDataCaller() As String
Private Function GetData() As String
    Console.WriteLine("On the background thread!")

    For index As Integer = 0 To 2
        Console.WriteLine("Background thread is working")
    Next

    Return "Yay, background thread got the data!"

End Function

Blocking子主函数()

    Console.WriteLine("On the main thread")
    Dim dataDelegate As New GetDataCaller(AddressOf GetData)

    Dim iar As IAsyncResult

    ' blocking approach; WaitOne() will block this thread from proceeding until the background thread is finished
    iar = dataDelegate.BeginInvoke(Nothing, Nothing)
    iar.AsyncWaitHandle.WaitOne()
    Dim result As String = dataDelegate.EndInvoke(iar)
    Console.WriteLine("On the main thread again, background result is: " + result)

End Sub

Private Sub GetData_Complete(ByVal iar As IAsyncResult)

    ' Downcast the IAsyncResult to an AsyncResult -- it's safe and provides extra methods
    Dim ar As System.Runtime.Remoting.Messaging.AsyncResult = DirectCast(iar, System.Runtime.Remoting.Messaging.AsyncResult)

    Dim dataDelegate As GetDataCaller = DirectCast(ar.AsyncDelegate, GetDataCaller)
    Dim result As String = dataDelegate.EndInvoke(iar)

    Console.WriteLine("On the main thread again, background result is: " + result)

End Sub

Private Delegate Function GetDataCaller() As String
Private Function GetData() As String
    Console.WriteLine("On the background thread!")

    For index As Integer = 0 To 2
        Console.WriteLine("Background thread is working")
    Next

    Return "Yay, background thread got the data!"

End Function
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

处理“大量”数据时的 WinForms UI 响应能力 的相关文章

  • 将 WPF 快捷键绑定到 ViewModel 中的命令

    我有一个使用 MVVM 模式的 WPF 应用程序 将按钮连接到 VM 非常简单 因为它们实现了 ICommand 我有一个工作原理类似的上下文菜单 下一步是为上下文菜单创建快捷键 我不知道如何让快捷键调用命令 这是一个例子
  • Perl Tk 模块有哪些缺点?

    与在 Perl 中创建 GUI 的其他解决方案相比 Tk 模块有哪些缺点 我最近浏览了 Perl 的各种 gui 模块 这是我的总结 免责声明 最终我发现现有模块都不能满足我的需求 所以我开始编写自己的 gui 工具包 Tk 工作起来很不错
  • 在 DataGridView 中隐藏行非常慢

    我在 Winforms 应用程序中有一个 DataGridView 大约有 1000 行 未绑定 和 50 列 隐藏一列需要整整 2 秒 当我想隐藏大约一半的行时 这就成为一个问题 private void ShowRows string
  • 使用 Matplotlib、PyQt 和 Threading 进行实时绘图导致 python 崩溃

    我一直在努力研究我的 Python 应用程序 但找不到任何答案 我有 PyQT GUI 应用程序 它使用 Matplotlib 小部件 GUI 启动一个新线程来处理 mpl 小部件的绘图 恐怕我现在通过从另一个线程访问 matplotlib
  • WinForms 中的 EF:如何过滤 BindingSource/DGW 中的数据 (.Local.ToBindingList())

    我按照本教程生成了 EF 模型 首先是数据库 和数据源http msdn microsoft com en us data jj682076 aspx http msdn microsoft com en us data jj682076
  • 当可能存在迭代器时替换并发集合是否是线程安全的?

    我一直在阅读各种内容 似乎这应该有效 但我想确定一下 我有一个静态属性 它应该是一个缓存 加上一些与缓存数据相关的其他功能 它将实际数据存储在 ConcurrentBag 中 并且有一个 IEnumerable 方法来 过滤并 从此包中生成
  • 向 Thunderbird 添加多个附件(从命令行)

    我尝试通过命令行创建带有多个附件的新消息 但这不起作用 thunderbird compose attachment etc mtab attachment etc fstab 仅附加第一个文件 第二个失踪了 上面的命令行有什么问题 PS
  • 当我使用 Image.FromFile() 时 FileNotFound

    我在这种情况下使用 Image FromFile string 方法 using System using System Collections Generic using System ComponentModel using Syste
  • 在Spring中使用什么样的“EventBus”?内置、Reactor、Akka?

    我们将在几周后启动一个新的 Spring 4 应用程序 我们希望使用一些事件驱动的架构 今年 我到处读到有关 Reactor 的内容 在网上查找时 我偶然发现了 Akka 所以现在我们有3个选择 春天的ApplicationEvent ht
  • Hazelcast 分布式锁与 iMap

    我们目前使用 Hazelcast 3 1 5 我有一个简单的分布式锁定机制 应该可以跨多个 JVM 节点提供线程安全性 代码非常简单 private static HazelcastInstance hInst getHazelcastIn
  • GUI Java 程序 - 绘图程序

    我一直试图找出我的代码有什么问题 这个想法是创建一个小的 Paint 程序并具有红色 绿色 蓝色和透明按钮 我拥有我能想到的让它工作的一切 但无法弄清楚代码有什么问题 该程序打开 然后立即关闭 import java awt import
  • 如何在C#背后的代码中动态创建数据模板并绑定TreeView分层数据

    我有一个场景 其中树视图动态更改其数据模板和数据绑定定义 我在 XAML 中创建了一个树视图 如下所示
  • 如何唤醒正在休眠的线程?

    我在加载事件中创建了一个线程 如下所示 Thread checkAlert null bool isStop false private void frmMain Load object sender EventArgs e checkAl
  • 控件更改时 ObjectDataSource 创建两次

    我将 ObjectDataSource 与 GridView 一起使用 并在代码隐藏中使用 OnObjectCreated 处理程序 如果我以编程方式更改 GridView 上的子控件值 则整个控件会在同一请求中再次进行数据绑定 如 OnO
  • 如何以编程方式对 WebBrowser 控件安全警报回答“是”

    我正在使用 WebBrowser 控件以编程方式访问单个网站 但每当我登录时 我都会收到此证书安全警报 由于我信任该网站 并且我还需要以编程方式自动登录 因此此对话框会妨碍我 我搜索了解决方案并发现一个和我类似的问题 https stack
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • Final字段的线程安全

    假设我有一个 JavaBeanUser这是从另一个线程更新的 如下所示 public class A private final User user public A User user this user user public void
  • IO 密集型任务中的 Python 多线程

    建议仅在 IO 密集型任务中使用 Python 多线程 因为 Python 有一个全局解释器锁 GIL 只允许一个线程持有 Python 解释器的控制权 然而 多线程对于 IO 密集型操作有意义吗 https stackoverflow c
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r

随机推荐

  • 创建 AWS Glue 爬网程序时访问被拒绝

    我尝试在 AWS Glue 中创建爬网程序 但出现错误 service AWSGlue statusCode 400 errorCode AccessDeniedException requestId
  • ColdFusion https 连接失败

    我有一个 API 在我的两个 Web 服务器之一上运行良好 但在另一台或我的本地计算机上运行不佳 相反 当我在登录过程中发送 https 请求时 我会遇到连接失败 这些请求非常简单 并且在运行它的三台服务器之一上运行没有问题 第一个如下
  • 捕获触发 DUP_VAL_ON_INDEX 的值

    鉴于这个例子 DUP VAL ON INDEX 异常 是否可以捕获违反约束的值 以便将它们记录下来 如果批量插入产生多个违规 方法是否相同 BEGIN want to capture 01 and 02 INSERT INTO Employ
  • WPF 列调整大小性能问题

    WPF 中是否存在与网格列大小调整相关的已知性能问题 我有一个应用程序 我需要在列中执行一些特定的操作 但对于所有不同的解决方案 我发现列调整大小变得很慢 这适用于我的列表中通常有超过 1000 个元素的情况 但我认为这对于 WPF 来说并
  • 入口服务类型

    我了解 Ingress 的原理 以及它如何通过将 Ingress 资源提供给 Ingress 控制器来路由到服务 我将 Docker for mac 与以下 Ingress 控制器一起使用 https github com kubernet
  • 循环遍历硬盘上的所有目录

    嘿大家我有这段代码 Private Sub Button1 Click ByVal sender As System Object ByVal e As System EventArgs Handles Button1 Click Dim
  • 水晶报表 - 分组依据

    我正在使用 Visual Studio 2008 并希望在报告中显示以下 SQL 查询 select name count from mytable group by name 我可以通过创建一个本质上是上述查询的数据集 由 名称 和 计数
  • C 中的动态多维数组

    阅读了几篇关于c中多维数组动态内存分配的文章 我发现了以下代码片段 文章链接 define COLS 5 int rptr COLS int main void int nrows 10 int row col rptr malloc nr
  • Facebook 应用程序使用 Facebook Api 发送好友请求

    我想在不使用 FBML 标签的情况下向我们的一些好友列表发送 Facebook 好友邀请
  • 从 URL 获取图像无法解码流:fileNotFoundException

    我知道这个问题已经被问过很多次了 但我尝试了很多解决方案 但没有一个有效 在 Android 上 我尝试从 URL 获取图像并将其放入图像视图中 不幸的是 我收到以下错误 E BitmapFactory Unable to decode s
  • 什么是 LD_LIBRARY_PATH 以及如何使用它?

    我参与开发一个Java项目 其中使用了一些C 组件 因此我需要Jacob dll 在 Windows 7 上 我不断得到java lang UnsatisfiedLinkError no JacobDB in java library pa
  • 通过代码添加的 Android 复选框外观不正确?

    我有一个非常基本的应用程序 我试图在其中插入动态复选框 并且可以让它们出现 但它们没有以正确的样式显示 参见下文 Foo 根据定义位于 LinearLayout 中 正在以编程方式添加栏 Foo 显示为灰色框 用于检查 Bar 显示为白色框
  • 获取此格式的日期时间并转换为 4 字节十六进制

    我有一个这种格式的日期时间 1999 12 31 09 00 00 来自十六进制值 F0C46C38 如何将上述格式的日期时间值转换为 4 字节十六进制 我上面发布的价值观是相互补充的 第二个代码块中的十六进制被反转 谢谢你 386CC4F
  • Cassandra 0.7 二级索引如何存储?

    我们一直在使用 Cassandra 0 6 现在拥有包含数百万个键的列族 我们有兴趣使用 0 7 中提供的新二级索引功能 但找不到任何有关如何存储新索引的文档 是否存在任何磁盘空间限制 或者索引的存储方式是否与键类似 因为它分布在多个节点上
  • magic_quotes_gpc() 的解药?

    我见过很多这样的 PHP 片段 function DB Quote string if get magic quotes gpc true string stripslashes string return mysql real escap
  • 无法加载 Rails 样式表中的语义 UI。解析值时出现很多错误

    我正在开发一个使用 Semantic UI 作为前端框架的 Rails 应用程序 我正在使用 Rails 5 我按照该网站上的说明进行操作 https github com Semantic Org Semantic UI Rails LE
  • 如何使用谷歌应用程序脚本洗牌每隔一列?

    如果 C 是 4 我想使用 google apps 脚本随机化 D E F G H I J K At the moment I use this inefficient time consuming code function shuffl
  • 使用多个命令的 Python paramiko 模块

    我有一个创建连接的类 我可以在通道关闭之前连接并执行 1 个命令 在另一个系统上 我可以执行多个命令 并且通道不会关闭 显然 这是我尝试连接的系统的配置问题 class connect newconnection def init self
  • Linux下如何给进程分配更多内存

    我正在 64 位 Fedora 16 上使用 CAD 程序 有一次该程序突然崩溃并完全退出 我最初的猜测是没有足够的内存可供该程序执行该操作 并且它退出了 为了测试它 我想为该特定程序分配更多内存 这样做时 如果其他程序没有足够的内存 我也
  • 处理“大量”数据时的 WinForms UI 响应能力

    我正在修改一个 Windows 窗体 以允许在后台加载数据 同时 UI 保持响应 数据的检索和绑定都需要相当长的时间 理想情况下 我会在后台执行这两项操作 但是对于我应该在后台执行哪种 UI 更新 如在主线程之外 存在一些模糊性 一个在后台