结合锁在线程中使用Invoke [英] Use of Invoke in thread combined with lock

查看:150
本文介绍了结合锁在线程中使用Invoke的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么将Invoke与线程中的锁一起使用有时会使应用程序挂起?

Why is it that the use of Invoke with the lock in thread hangs the application at times?

推荐答案

通常,强烈建议不要从锁定的代码块中使用Invoke().

参见 http://stackoverflow.com/questions/1932108/c-invoke-event-from -locked-block [ ^ ]

该线程与您的问题并不直接相似,但是答案中提到的要点也可能适用于您.
In general it''s highly recommended not to use Invoke() from a locked block of code.

See http://stackoverflow.com/questions/1932108/c-invoke-event-from-locked-block[^]

The thread is not directly similar to your question, but the points mentioned in the answer will probably apply to you as well.


如果在UI线程上使用了相同的锁,它将创建死锁. .很容易解释.

首先,让我解释一下,Invoke 不需要与UI线程互锁.在解释了为什么"不需要"之后,我将解释为什么"不需要"(由于可能的死锁).

调用动态创建一些委托实例,这种委托的类型是多态的(方法配置文件可以不同).该委托实例将参数方法添加到其调用列表中.委托实例与所有调用参数(在实例方法的情况下包括"this")一起放在一些内部数据结构中;并将此数据结构实例放入UI线程的一些内部队列中.因此,Invoke的参数是方法,在调用Invoke的线程中永远不会调用该方法(除非它与UI处于同一线程).实际调用仅在从队列中删除结构时才在UI线程上完成.这样,已经保证Invoke和实际的委托调用不会通过队列进行序列化访问任何关键区域.只需记住,始终在UI线程上调用用作Invoke参数的方法.

您可能只需要将线程代码的某些部分与第三个线程(如果有)互锁,而无需与UI线程互锁.

如果您从提示/技巧"部分阅读了我的文章,则可以很好地了解Invoke的工作原理:不得"部分.假设您在线程(调用Invoke)和UI线程之间共享一个锁对象.它会产生死锁:如果输入代码,则进入锁定区域,然后线程进入等待状态,等待返回调用的方法.如果执行此操作,则UI线程尚未处理您发送给它的委托.相反,UI线程处理当前消息,然后将您的委托从队列中移出.如果UI使用相同的锁对象,它将等待直到释放它.它没有被释放,因为您已锁定并等待调用结束.实际上,您的线程正在等待锁中的UI线程,而不是释放它. UI线程正在锁的入口处等待您的线程.

这种情况可能会有不同的变化.在所有情况下,某些线程都互相等待.这叫做死锁.

—SA
It creates a deadlock if the same lock is used on the UI thread. It''s easy to explain.

First, let me explain, that Invoke does not require inter-locking with the UI thread. After I explain why "does not require", I''ll explain why "must not" (because of possible deadlock).

Invoke dynamically creates some delegate instance, the types of such delegate are polymorphous (method profiles can be different). This delegate instance adds the parameter method to the its invocation list. The delegate instance is put in some internal data structure along with all the calling parameters (including "this" in case of instance method); and this data structure instance is put in some internal queue of the UI thread. So, the parameter of Invoke is the method, which is never called on the thread calling Invoke (unless it is the same thread as UI). The actual call is only done on UI thread when it removed the structure from the queue. In this way, Invoke and the actual delegate call are already guaranteed not to access any critical area through serialization by the Queue. Just remember that a method used as an Invoke parameter is always called on UI thread.

You only may need to inter-lock some section of the thread code with third thread, if any, but never with the UI thread.

You can get a good idea how Invoke works if you read my article from the Tips/Tricks section: Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^]. In that article I show the code which introduces the same mechanism for the custom thread.

Now, I need to explain the "must not" part. Let''s say you share a lock object between your thread (calling Invoke) and UI thread. It can create a deadlock: you enter locked area if the code and then the thread goes to the wait state waiting for the return of the invoked method. If you do this, UI thread is not yet processing the delegate you sent to it; instead, UI thread process current messages and than takes your delegate from the queue. If UI uses the same lock object, it waits until it is released. It it not released, because you have taken the lock and waiting the end of invocation. Effectively, your thread is waiting for UI thread inside the lock and not releasing it; UI thread is waiting your thread at the entry of the lock.

There can be different variations of this situation. In all cases some threads wait for each other; it''s called a deadlock.

—SA


这篇关于结合锁在线程中使用Invoke的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆