ManualResetEvent WaitOne 阻止我的 CollectionView 的所有者线程

2023-12-26

我编写了一个 WPF WizardFramework,它使用一些在后台执行一些操作BackgroundWorker。在处理时可能会发生我必须更新ObservableCollection这与我的用户界面绑定。

对于这种情况我写了一个ThreadableObservableCollection,它提供了线程安全的方法Insert, Remove and RemoveAt。虽然我使用的是.NET 4.5,但我无法获得BindingOperations.EnableCollectionSynchronization没有许多其他无效访问异常的情况下工作。我的Collection好像:

  public class ThreadableObservableCollection<T> : ObservableCollection<T>
  {
    private readonly Dispatcher _dispatcher;
    public ThreadableObservableCollection()
    {
      _dispatcher = Dispatcher.CurrentDispatcher;
    }

    public void ThreadsafeInsert(int pos, T item, Action callback)
    {
      if (_dispatcher.CheckAccess())
      {
        Insert(pos, item);
        callback();
      }
      else
      {
        _dispatcher.Invoke(() =>
          {
            Insert(pos, item);
            callback();
          });
      }
    }

    [..]
  }

当我在应用程序中使用向导时,这按预期工作。现在我正在使用 NUnit 为应用程序编写一些集成测试。

有一个侦听器等待 WizardViewModel 完成其工作并查找注入到 Steps-Collection 中的一些页面。异步工作完成后,我可以使用验证来检查视图模型状态。

不幸的是我正在使用ManualResetEvent等待向导关闭。这看起来如下:

  public class WizardValidator : IValidator, IDisposable
  {
    private WizardViewModel _dialog;
    private readonly ManualResetEvent _dialogClosed = new ManualResetEvent(false);

    [..]

    public void ListenTo(WizardViewModel dialog)
    {
      _dialog = dialog;
      dialog.RequestClose += (sender, args) => _dialogClosed.Set();
      dialog.StepsDefaultView.CurrentChanged += StepsDefaultViewOnCurrentChanged;

      _dialogClosed.WaitOne();
    }

    [..]
 }

现在有一个问题: 当应用程序运行时,UI 线程不会被阻塞,集合可以毫无问题地更新。但在我的测试用例中,我初始化 ViewModel(因此集合)的“主”线程是一个被测试代码阻止的 AppDomainThread。现在我的ThreadsafeInsert想要更新集合但无法使用 AppDomain 线程。

但我必须等待向导完成,我该如何解决这种僵局呢?或者有更优雅的解决方案吗?

edit:我通过检查是否存在用户界面来解决这个问题,然后才在应用程序线程上调用,否则我会在另一个线程上故意更改集合。这并不能阻止异常,但测试无法识别......尽管如此,项目还是被插入了,只有NotifyCollectionChanged- 不调用处理程序(无论如何,它仅在 UI 中使用)。

  if (Application.Current != null)
  {
    Application.Current.Dispatcher.Invoke(() =>
      {
        Steps.Insert(pos, step);
        stepsView.MoveCurrentTo(step);
      });
  }
  else
  {
    new Action(() => Steps.Insert(pos, step)).BeginInvoke(ar => stepsView.MoveCurrentToPosition(pos), null);  
  }

这是一个丑陋的解决方法,我仍然对干净的解决方案感兴趣。

有没有办法使用备用调度程序来创建(例如)整个 ViewModel 并使用它来更改我的集合?


正如我看到的主要问题是主线程被阻塞并且其他操作也试图在主线程中执行?不阻塞主线程怎么样,如下所示:

// helper functions
public void DoEvents()
{
    DispatcherFrame frame = new DispatcherFrame();
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
        new DispatcherOperationCallback(ExitFrame), frame);
    Dispatcher.PushFrame(frame);
}

public object ExitFrame(object f)
{
    ((DispatcherFrame)f).Continue = false;

    return null;
}

// in your code:  
while(!_dialogClosed.WaitOne(200)) 
    DoEvents();

如果它没有帮助,那么我想需要尝试一些 SynchronizationContext 解决方法。

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

ManualResetEvent WaitOne 阻止我的 CollectionView 的所有者线程 的相关文章

  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • SSH 主机密钥指纹与模式 C# WinSCP 不匹配

    我尝试通过 WinSCP 使用 C 连接到 FTPS 服务器 但收到此错误 SSH 主机密钥指纹 与模式不匹配 经过大量研究 我相信这与密钥的长度有关 当使用 服务器和协议信息 下的界面进行连接时 我从 WinSCP 获得的密钥是xx xx
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐

  • 如何在Java中使用图形输入板? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 几周前 我购买了 Wacom Bamboo 绘图板 我想开发一个小型的java应用程序 它可以捕获用户
  • Titanium 安装后 NPM install -g 不起作用

    我已经在我的 mac 上安装了 Titanium 现在每当我尝试全局安装任何 npm 软件包时都会失败 我的安装的输出是 npm http 304 https registry npmjs org loggly npm http GET h
  • 如何创建一个开关案例,案例是间隔?

    我想创建一个开关 案例 其中案例可以有间隔作为条件 例如 switch 1 lt 21 do one stuff 21 31 do another 我怎样才能达到这个结果 在Python 3 10中 https docs python or
  • Azure 上的 Asp.net MVC 5.2.2

    将 mvc nuget 包从版本 5 1 0 升级到 5 2 2 后 我们在 Azure 上的计算机 webrole 拒绝启动 Web 角色 它处于回收状态 我在事件日志中发现了一个错误 The description for Event
  • 如何将字符串截断为最多 N 个字符?

    预期的方法String truncate usize https doc rust lang org std string struct String html method truncate失败是因为它不考虑 Unicode 字符 考虑到
  • 如何处理 cv::VideoCapture 解码错误?

    我使用 OpenCV 的 VideoCapture 使用 ffmpeg 支持编译 从 IP 摄像机流式传输 H264 内容 到目前为止 一切正常 但每隔一段时间我就会遇到解码错误 我猜是来自 ffmpeg h264 0x103006400
  • 查找单个元素上的所有数据属性

    有人知道一种快速有效的方法来从单个元素中获取所有数据属性吗 我意识到 jQuerys data 会这样做 但是它不会给我使用 attr 设置的数据属性 除非我首先使用 data 选择数据属性 此外 您无法通过使用 data 添加的数据属性来
  • 如何在 Swift 中将 [Int8] 转换为 [UInt8]

    我有一个仅包含字符的缓冲区 let buffer Int8 然后我需要将其传递给一个函数process以 UInt8 作为参数 func process buffer UInt8 some code 传递 Int8 缓冲区以转换为 Int8
  • 按年龄对某个范围内的用户进行分组

    我有一些数据需要进行一些统计 我需要按年龄对用户进行分组 var byAge displayResult GroupBy x gt x Age 我可以按照上面的方法做 然而 这给了我 19 20 21 等年龄 我想要的是按 10 岁对年龄进
  • 使用 REST API 创建项目后,将用户作为管理员分配给项目 - Azure DevOps

    我正在尝试将用户分配为项目的管理员 并通过 Azure DevOps 中的 REST API 更改所有者 你们中的任何人都可以向我指出一些如何完成此操作的文档吗 我已经查看了 UserEntitlements API 和 Project A
  • 重试 HTTP(S) POST,直到在 Android 上成功

    我有一些数据将通过 http s 从 Android 应用程序发送到服务器 需要按顺序发送 是否已经存在一种对 http 请求进行排队 针对同一服务器 并重试它们直到完成 不一定成功 的方法 我的问题是如果没有网络覆盖 http请求可能会失
  • 如何更改C# Winform中文本框中某些子字符串的字体颜色?

    如果我想将文本文件上传到文本框中并希望通过字体颜色更改突出显示某些单词 我知道我需要编写TextBox ForeColor Color SomeColor 但如果我想要那个并非所有文本都会出现在same color 只有一些子串 我怎样才能
  • 在 ASP.NET 中拉取多个记录集时的 DataReader 或 DataSet

    我有一个 ASP NET 页面 其中有一堆需要填充的控件 例如下拉列表 我想单次访问数据库并带回多个记录集 而不是为每个控件进行往返 我可以带回 DataSet 中的多个表 或者可以带回 DataReader 并使用 NextResult
  • 为什么SIGPIPE存在?

    据我了解 SIGPIPE只能作为以下结果发生write 它可以 并且确实 返回 1 并设置errno to EPIPE 那么为什么我们会有额外的信号开销呢 每次我使用管道时我都会忽略SIGPIPE并且从未因此感到任何疼痛 我是否错过了什么
  • onDraw() 没有被调用

    我正在修复某人的 Android 应用程序 它最初是为 2 1 制作的 我正在努力让它工作到 4 0 不幸的是 制作该应用程序的人不在身边 所以我只能使用他的代码 该应用程序实现了自定义滑块 水平和垂直 我固定了垂直滑块 但无法使水平滑块工
  • 如何在非主线程中获取剪贴板数据?

    我正在尝试使用以下代码从剪贴板获取数据 private void TestBtn Click object sender EventArgs e Thread sampleThread new Thread SampleMethod sam
  • 如何通过 Google Sheets API 更新多个单元格?

    我正在尝试更新并从谷歌表格中获取一些结果 它正在工作但速度很慢 我需要batchUpdate并获取数据 这是我的脚本 foreach import cels as celu gt valoare range ins celu valueRa
  • 使用渐变但不混合颜色

    我不知道这是一个愚蠢的问题还是类似的问题 但我想要一个div用一种颜色填充一定比例 其余部分用另一种颜色填充 以及梯度属性 div background linear gradient to right 000 50 fff 50 Resu
  • Unicode 中为什么会有重复的字符?

    我可以看到一些重复的字符Unicode http en wikipedia org wiki Unicode 例如 字符 C 可以由代码点 U 0043 和 U 0421 表示 为什么会这样呢 正如其他人所指出的 您在这里的主要谬误是混淆了
  • ManualResetEvent WaitOne 阻止我的 CollectionView 的所有者线程

    我编写了一个 WPF WizardFramework 它使用一些在后台执行一些操作BackgroundWorker 在处理时可能会发生我必须更新ObservableCollection这与我的用户界面绑定 对于这种情况我写了一个Thread