【问题标题】:c++/cli c# winforms cross-thread operation sometimes possiblec++/cli c# winforms 有时可以进行跨线程操作
【发布时间】:2015-06-29 15:57:59
【问题描述】:

我正在使用 c++/cli(也应该适用于 c#)并创建一个 winforms 程序。

我有几行代码可以在 DataGridView 中编辑数据。代码由 FileSystemWatcher 事件执行,但它可以由后台工作程序或简单线程执行。但是,它不是由 UI 线程执行的。
DGV 放置在 TabControl 的选项卡上。在包含 DGV 的选项卡具有焦点的情况下执行代码时,代码将失败并出现众所周知的预期异常“跨线程操作无效”。

但是当另一个选项卡获得焦点时,代码会顺利执行。我假设 DGV 在未显示时未更新,导致代码在这种情况下运行良好。但这意味着向消息队列发送 WM_PAINT 等消息取决于 DGV 的可见性(显示与否),如果不可见,则必须在 DGV 再次显示时发送这些消息。

这是正确的吗?
DGV显示(不显示)时,代码执行有何不同?

【问题讨论】:

  • 很难给您一个确切的原因,说明您的代码在没有代码 sn-p 的情况下表现如何。是在后台工作人员中进行更新的代码还是类似的东西?
  • 代码是通过FileSystemWatcher事件执行的,但基本上和后台worker或者线程执行是一样的。

标签: c# multithreading winforms c++-cli


【解决方案1】:

您的代码根本上是错误的,但这并不意味着您一定会被提醒。当控件不可见时它不会爆炸,不需要更新它所以不需要做任何线程不安全的事情所以也不例外。

必须解决根本问题。使用 FileSystemWatcher::SynchronizingObject 属性非常容易。只需在表单构造函数中将其设置为 this 即可。现在该事件在 UI 线程上自动引发,您可以在控件属性上聚会,而不会被指关节敲击。修复:

    MyForm(void)
    {
        InitializeComponent();
        fileSystemWatcher1->SynchronizingObject = this;
    }

假设您将 FSW 从工具箱中拖放到表单上。根据需要进行调整。

【讨论】:

  • 为什么根本上是错误的,根本问题是什么?除了没有通过调用访问 DGV 之外,还有其他问题吗?我打算使用调用来解决问题,所以我知道它失败的原因。我更多地询问“有时崩溃”的原因。不过,感谢您指出这个简单的解决方案。但请回答问题。
  • 当您不使用 SynchronizingObject 属性时,FSW 在工作线程上引发其事件。工作线程不允许直接更新 UI,只有在 UI 线程中这样做才是合法的。或者换句话说,控件不是线程安全的。除了 SynchronizingObject,使用表单的 BeginInvoke() 方法是另一种解决方法。
  • 我知道 FSW 在另一个线程上运行,并且只允许从 UI 线程更新 UI 控件。我不想被告知为什么当 DGV 可见时它会失败(因为我已经知道了)。我想知道为什么 DGV 未显示时它不会失败。这种情况有什么区别?
  • 我在第一段中解释了这一点。切换选项卡时它是不可见的,不需要更新它,不需要使用线程不安全的代码,也不例外。不运行的代码不能抛出异常。想不出别的说法了,应该有点直观吧。
  • 好吧,也就是说DGV只有在可见的时候才更新,不可见的时候,变成可见的时候才更新?这就说得通了。我只是没有得到“不需要更新它”的意思,实际上没有更新。理解我这边的问题。感谢您的澄清。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 2016-08-15
相关资源
最近更新 更多