- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
任何时候初学者都会问类似这样的问题:How to update the GUI from another thread in C#? ,答案很直接:
if (foo.InvokeRequired)
{
foo.BeginInvoke(...)
} else {
...
}
但是真的好用吗?在非 GUI 线程执行 foo.InvokeRequired
之后,foo
的状态会发生变化。例如,如果我们在 foo.InvokeRequired
之后但在 foo.BeginInvoke
之前关闭表单,调用 foo.BeginInvoke
将导致 InvalidOperationException
:在创建窗口句柄之前无法在控件上调用 Invoke 或 BeginInvoke。如果我们在调用 InvokeRequired
之前关闭窗体,则不会发生这种情况,因为即使从非 GUI 线程调用它也是 false
。
另一个例子:假设
foo
是一个
TextBox
。如果您关闭表单,并且在非 GUI 线程执行
foo.InvokeRequired
(这是错误的,因为表单已关闭)和
foo.AppendText
之后,它将导致
ObjectDisposedException
.
相比之下,我认为使用 WindowsFormsSynchronizationContext
更容易 - 使用 Post
发布回调只有在线程仍然存在时才会发生,并且使用 Send 进行同步调用
如果线程不再存在,则抛出 InvalidAsynchronousStateException
。
使用 WindowsFormsSynchronizationContext
不是更简单吗?我错过了什么吗?如果它不是真正的线程安全,我为什么要使用 InvokeRequired-BeginInvoke 模式?你觉得哪个更好?
最佳答案
WindowsFormsSynchronizationContext
通过将自身附加到绑定(bind)到创建上下文的线程的特殊控件来工作。
所以
if (foo.InvokeRequired)
{
foo.BeginInvoke(...)
} else {
...
}
可以替换为更安全的版本:
context.Post(delegate
{
if (foo.IsDisposed) return;
...
});
假设 context
是在与 foo
相同的 UI 线程上创建的 WindowsFormsSynchronizationContext
。
这个版本避免了你引起的问题:
Right after non-GUI thread executes foo.InvokeRequired the state of foo can change. For example, if we close form right after foo.InvokeRequired, but before foo.BeginInvoke, calling foo.BeginInvoke will lead to InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created. This wouldn't happen if we close the form before calling InvokeRequired, because it would be false even when called from non-GUI thread.
如果您使用多个消息循环或多个 UI 线程,请注意 WindowsFormsSynchronizationContext.Post
的一些特殊情况:
WindowsFormsSynchronizationContext.Post
仅当创建委托(delegate)的线程上仍有消息泵时才会执行委托(delegate)。如果没有什么都没有发生,也没有引发异常。Application.Run
例如)委托(delegate)将执行(这是由于系统为每个线程维护一个消息队列,而不知道是否有人从中提取消息这一事实)WindowsFormsSynchronizationContext.Send
将抛出 InvalidAsynchronousStateException
如果它绑定(bind)到的线程不再存在。但是如果它绑定(bind)的线程是事件的并且不运行消息循环它不会立即执行但仍然会被放置在消息队列中并在 Application.Run< 时执行
再次执行。如果 IsDisposed
在自动处理的控件(如主窗体)上调用,则这些情况都不应意外执行代码,因为委托(delegate)将立即退出,即使它在意外时间执行也是如此。
危险的情况是调用 WindowsFormsSynchronizationContext.Send
并考虑代码将被执行:它可能不会,现在有办法知道它是否做了任何事情。
我的结论是,只要使用得当,WindowsFormsSynchronizationContext
是更好的解决方案。
在复杂的情况下,它可能会产生一些微妙的问题,但具有一个消息循环的常见 GUI 应用程序只要应用程序本身就一直存在,就永远没问题。
关于c# - 为什么 InvokeRequired 优于 WindowsFormsSynchronizationContext?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5246023/
我想显示一个图像(大于 iPhone 的屏幕),用户可以滚动。不难,我已经用这段代码完成了:在我的 .h 文件中 @interface mappa1 : UIViewController { IBO
bash 联机帮助页说: Redirecting Standard Output and Standard Error Bash allows both the standard output (fi
我将大量数据绑定(bind)到 TreeView 控件,因为数据是自然的类别层次结构。问题是它有很多。我已经设法通过仅绑定(bind)那些出现在可见树中的节点来消除大量开销,但这仍然在 ViewSta
我正在尝试为 mysql 操作与 redis 操作制作基准测试脚本。 这是我尝试过的: 1./ List of comment ids with a separate hash of comment
我很想知道是否有比 FileObserver 更好的方法来监视目录的文件更改/创建/删除。 FileObserver 需要持续引用它,这需要持续运行的服务,这很困难,也是一种不好的做法,对吧? 对于如
我创建了一个带有 NSOpenGLView 的窗口,我正在将 openGL 内容渲染到其中。 我想向 View 添加一些按钮和文本字段:我可以使用界面生成器(或代码)添加 NSTextFields 和
如何编码 JAXBElement 列表? 例如,我有一个无法注释的 POJO: public class APojo { private String aString; public APojo()
我正在开发一个博客,我的客户希望在其中使用大量图像(文章、标题、广告等)。他几乎不想要任何文本,因为他希望用阿拉伯语开发博客并且他对网络浏览器支持的任何字体都不满意,他也不想采用 EOT,他将每天更新
我想在文本字段上添加一个标签,该标签会在用户键入时发生变化。问题是文本字段的插入符号位于标签后面(如果我将标签放在文本字段前面)。我始终可以使文本字段的背景透明,并在标签和文本字段后面添加另一个禁用的
我正在尝试在 iOS 应用程序中创建一个特定的布局,其中“背景”是一个 MKMapView,覆盖层是一个 UIScrollView。这个想法是有两个屏幕,一个带有 map ,另一个带有一些附加信息。用
我需要在 UITableViewController 上放置一个 UIView,目前我是这样放置的 [self.navigationController.view addSubview:searchV
我有一个非常简单的问题要问:我需要在屏幕右下角的 ImageView 上放一个小 Logo ,整个屏幕都很大,但我不知道如何设置坐标或如何设置说 ImageViews 处于相对位置。 像这样: 最佳答
我试图让 mapView 覆盖整个 UITableViewCell 并禁用此 mapView 上的所有用户事件,但仍然可以单击单元格。但是,此 mapView(即使我将 subview 发送回)正在拦
我们即将获得 Java EE6(使用 Glassfish v3 作为引用实现)。计划发布时间为 12 月 9 日。虽然仍有相当多的公司正在努力将他们的代码库从早期版本迁移到 EE5,但我们处于开始开发
为什么(在 WPF、C#、 Entity Framework 中)将 ListBox 绑定(bind)到在 ObjectSet 上创建的 ObservableCollection(来自 Entity框
在 hibernate 中使用 @NamedQuery 而不是 @NamedNativeQuery 有什么好处,反之亦然。我无法发现确切的区别或在什么情况下我们应该使用 @NamedQuery 而不是
在 Dart 中,检查值是否为 == null似乎类似于检查它是否is Null .为什么前者更可取? 最佳答案 这是您正在进行的比较类型。在 == null ,您正在将对象/原始对象与 null 进
我使用的是 Java 1.6。我有一组项目,每个项目都有一个名称和一组组件。每个组件也有一个名称。 Set Class Item String name Set Class Compo
如果我想在我的应用程序中支持脚本,是否 scriptcs提供比仅使用普通 Vanilla 的任何特殊优势 Roslyn脚本引擎? 最佳答案 不幸的是,目前还没有太多关于托管 scriptcs 的文档,
我正在我的应用程序中使用 Struts 和 Spring jdbc 模板。 我必须在我们的代码中使用 Hibernate 模板。 谁能告诉我为什么要使用 Hibernate 模板? 使用 Spring
我是一名优秀的程序员,十分优秀!