WinForms 多线程:仅当前一个更新完成时才执行 GUI 更新

2024-03-22

我有带有一些后台处理的多线程应用程序。它有长时间运行的 UI 更新(在 UI 线程本身上),它们是通过众所周知的从后台线程调用的MSDN 上的资源 http://msdn.microsoft.com/en-us/library/757y83z4%28VS.71%29.aspx。我无法缩短这些 UI 更新,因为它们最终是在外部库中完成的 (1)。

现在,从那个后台线程,我想异步调用(使用BeginInvoke())这些更新在 UI 线程上进行,但前提是先前的更新尚未完成。如果没有,我想跳过此更新。这将防止 Windows 消息队列溢出,以防调用速度快于被调用方法的执行速度。

我目前的解决方案是这样的:在 UI 线程上执行的方法中,我确实进入和退出 ReaderWriterLockSlim 实例。在后台线程上,我尝试以零超时进入实例。成功后,我调用“BeginInvoke()”,然后再次退出。如果不成功,我会完全跳过方法调用。

public void Update(double x, double y)
{
    _updateLock.EnterWriteLock();
    try
    { //...long running task... }
    finally
    { _updateLock.ExitWriteLock(); }
}
//....
void Provider_PositionChanged(object sender, SpecialEventArgs e)
{
   if (_updateLock.TryEnterWriteLock(0)) //noone is currently executing an update?
   {
       try { myUiControl.BeginInvoke(/*...*/); }
       finally { _updateLock.ExitWriteLock(); }               
   }

这一切都有效,但是有更优雅的解决方案吗?如何从一个线程简单地测试某个方法是否在任何(其他)线程上执行?

  • 注意:使用Invoke()(代替BeginInvoke())不是一个选项,因为这会阻塞我的后台线程,阻止其他东西在那里执行。
  • (1)它是 MapXtreme,一个地图解决方案,我想要平移/缩放大型位图地形数据,并更新一些功能。
  • 附言。这个问题有些相关,但涵盖了不同的方面:Winforms 多线程:每次在 UI 线程上调用方法时是否需要创建一个新的委托? https://stackoverflow.com/questions/4283689/winforms-multithreading-is-creating-a-new-delegate-each-time-when-invoking-a-met

感谢您的任何答复!

UPDATE:汉斯·帕桑特(Hans Passant)帮助我回答了他的问题。请参阅下面的解决方案。希望这对其他人也有帮助。

/// <summary>
/// This class enqueues asynchronously executing actions (that are running on another thread), but allows
/// to execute only one action at a time. When busy, newly enqueued actions are dropped.
/// Any enqueued action is required to call Done() on this when it has finished, to allow further actions
/// to execute afterwards.
/// </summary>
/// <remarks>This class is intended to help prevent stacking UI-Updates when the CPU or other resources
/// on the machine are not able to handle the amount of updates requested. However, the user
/// must keep in mind, that using this class may result
/// in dropped updates and that the last requested update is not always executed.</remarks>
public class ActionBouncer
{
    /// <summary>
    /// A event that signals the idle/busy state. Idle means, that no action is currently executing.
    /// </summary>
    private ManualResetEvent _idle = new ManualResetEvent(true);

    /// <summary>
    /// Enqueues the specified action, executing it when this bouncer
    /// is currently idle.
    /// </summary>
    /// <param name="action">The action.</param>
    public void Enqueue(Action action)
    {
        if (_idle.WaitOne(0))  //are we idle now? (Remark: This check and the reset below is not thread-safe (thanks to s.skov))
        {
            _idle.Reset(); //go to busy state
            action(); //execute the action now.
        }//else drop the action immediately.
    }

    /// <summary>
    /// Signal the bouncer, that the currently executing asynchronous action is done, allowing 
    /// subsequent requests to execute.
    /// This must get explicitly called (in code) at the end of the asynchronous action. 
    /// </summary>
    public void Done()
    {
        _idle.Set();               
    }
}

这段代码实际上并没有做你想要它做的事情。委托目标需要一段时间才能开始运行。在此之前,您的工作线程可能多次获取写锁。只有当 Update() 方法正忙于执行时,才会无法获取锁。

ManualResetEvent 就是您想要的。对其进行初始化设置。当您BeginInvoke()时重置()它,在Update()结束时设置()它。现在您可以使用 WaitOne(0) 进行测试。

请注意此方法的一个极端情况:您的 UI 很可能not显示最后一次更新。

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

WinForms 多线程:仅当前一个更新完成时才执行 GUI 更新 的相关文章

随机推荐

  • 调用 MVC4 Razor DisplayTemplate,生成 HTML,但未渲染到浏览器

    我有一个迭代集合并调用的视图DisplayFor 对于集合中的每个元素 我需要手动迭代 而不是将集合传递给 DisplayFor 以便告诉模板是否应该在列表中绘制中断 列表中的项目只有两种类型 按它们排序 因此我只需要显示此中断一次 我的模
  • 具有高级混合索引的 Numpy 子数组分配

    原问题 当我尝试分配数组的某些元素时 我收到一条非常奇怪的错误消息 我使用切片和一组索引的组合 请参阅以下简单示例 import scipy as sp a sp zeros 3 4 5 b sp ones 4 5 I sp array 0
  • 本地主机和带有 Auth0 的 CORS 不允许我登录

    我正在制作一个 React 应用程序并尝试使用 Auth0 进行身份验证 尝试登录后 它返回 XMLHttpRequest 无法加载https my domain auth0 com 用户名密码 登录 https my domain aut
  • 了解 matplotlib:plt、figure、ax(arr)?

    我并不是很陌生matplotlib我非常羞愧地承认我一直使用它作为尽可能快速 轻松地获得解决方案的工具 所以我知道如何获得基本的情节 子情节和东西 并且有相当多的代码可以不时地重用 但我没有 深入的 呃 知识 matplotlib 最近我想
  • R 中的 Reduce() 对相似变量名导致错误

    我有 19 个由 lapply 和 split 操作生成的嵌套列表 这些列表的形式如下 list1 Var col1 col2 col3 A 2 3 4 B 3 4 5 list2 Var col1 col2 col3 A 5 6 7 B
  • MYSQL 选择一列中的两个值

    我需要从 mysql 表中选择一行 该表中有两行具有相同的值 TABLE articleId keywordId 现在我需要选择一篇文章 其关键字 Id 1 以及关键字 Id 12 每个关键字的链接都有自己的记录 如何执行一个选择查询来知道
  • tomcat 7.0.42 上的 403 访问被拒绝

    我有错误tomcat 7 0 42 上的 403 访问被拒绝访问 Tomcat Manager 应用程序时 这就是我所拥有的tomcat 用户 xml文件 我曾多次尝试更换角色 但没有成功 注意 我从 NetBeans 7 3 1 启动 停
  • 获取 icloud Web 服务端点以获取数据

    我的问题可能看起来很愚蠢 但我在谷歌上进行了太多搜索后才问这个问题 但没有任何线索 我正在使用 iCloud 网络服务 为此 我已将此 Python 代码转换为 PHP https github com picklepete pyiclou
  • ASP.NET Identity 的 IUserSecurityStampStore 接口是什么?

    查看 ASP NET Identity ASP NET 中的新成员身份实现 我在实现自己的接口时遇到了这个接口UserStore Microsoft AspNet Identity Core dll namespace Microsoft
  • 检查 bash 中的索引数组是稀疏还是密集

    我在 bash 中有一个动态生成的索引数组 想知道它是否是sparse or dense 如果在最后一个条目之前有未设置的索引 则数组是稀疏的 否则数组是密集的 该检查应该在每种情况下都有效 即使是空数组 非常大的数组 扩展时超过 ARG
  • 如何聚焦未停靠的 Chrome 调试窗口的相应选项卡?

    在开发时 我经常在 Chrome 浏览器中打开很多选项卡 我总是在单独的窗口中使用未固定的 Chrome DevTools 假设我已经打开给定选项卡的 DevTools 然后在另一个选项卡中对 SO 进行了一些搜索 那么 如果我再次聚焦 C
  • 我可以解析外部网页的目录列表吗?

    是否可以解析外部网页的目录列表 因为该网页是可访问的 并且当我访问它时它会显示文件列表 我只想知道是否可以在 PHP 中动态解析文件以及如何解析 谢谢 抱歉不清楚 我的意思是目录列表 例如 http www ibiblio org pub
  • JComboBox 弹出菜单不出现

    我在 JPanel 中有一个 JComboBox 它本身嵌套在其他几个 JPanel 中 它填充了枚举的成员 我遇到了一个问题 当我单击展开按钮时 弹出菜单不会出现 以下是我迄今为止收集到的信息 1 第一次点击展开按钮没有任何反应 第二次单
  • LINQ 基于 IList 从 IList 中删除某些元素 [重复]

    这个问题在这里已经有答案了 如何使用 LINQ 从一个基于另一个 IList 的 IList 中删除某些元素 我需要从 list1 中删除 ID 出现在 list2 中的记录 下面是代码示例 class DTO Prop int ID Pr
  • 如何在 Windows 10 Universal 中获取设备的唯一标识符?

    这是我为 Windows Universal 8 1 获取唯一 DeviceID 的旧实现 但 HardwareIdentification 类型不再存在 private static string GetId var token Hard
  • 如何在android应用程序中从twitter获取用户信息?

    我正在将 Twitter 集成到我的 Android 应用程序中 我可以为用户授权该应用程序 现在 我正在寻找一个 API 它可以为我提供登录用户的信息 如名字 姓氏 电子邮件等 我已经为 Facebook 做了这个 facebook re
  • Java中如何查找未关闭的I/O资源?

    Java 中的许多 I O 资源 例如 InputStream 和 OutputStream 在使用完毕后需要关闭 如前所述here http www coderanch com t 202922 Performance java Uncl
  • Matlab中如何imwarp转点?

    我正在使用 Matlab 将图像转换为目标图像 我有几何变换 tform 例如这是我的 tform 1 0235 0 0022 0 0607 0 0 0276 1 0002 0 0089 0 0 0170 0 0141 1 1685 0 1
  • 如何将 openssl-sys 箱静态链接到共享库?

    我正在使用一个依赖于的库openssl 系统 https github com sfackler rust openssl 根据文档 如果我指定OPENSSL STATIC 1作为环境变量 OpenSSL 将静态链接到共享库输出中 Due
  • WinForms 多线程:仅当前一个更新完成时才执行 GUI 更新

    我有带有一些后台处理的多线程应用程序 它有长时间运行的 UI 更新 在 UI 线程本身上 它们是通过众所周知的从后台线程调用的MSDN 上的资源 http msdn microsoft com en us library 757y83z4