多个Control.BeginInvoke/Invoke调用会按顺序执行吗?

16
我需要知道Control.BeginInvoke和Control.Invoke调用是否按照它们被调用的顺序执行。
我有以下场景:
1. UI线程已被阻塞 2. WCF线程调用Control.BeginInvoke 3. WCF线程调用Control.Invoke(或可能是再次BeginInvoke) 4. UI线程被解除阻塞 5. ??
步骤1-4的执行顺序保证按照所示顺序进行(从技术上讲,顺序不一定保证如此,但我要问的问题只与顺序相关)。
我的问题是在步骤2中的BeginInvoke调用之前,步骤3中的Invoke/BeginInvoke调用是否有任何机会被执行?
另外,请不要评论阻止UI线程。
4个回答

12
在您的情况下,步骤2将始终在步骤3之前执行。在UI线程上的BeginInvoke将按照排队的顺序执行。
UI线程实际上是一个消息泵,它具有仅有一个线程消费的单个消息队列,因此保证工作项将按照它们被排队的顺序执行。
使用Delegate.BeginInvoke时,执行顺序可能是非顺序的。

1
那么关于同步Invoke调用可能在异步BeginInvoke调用之前执行的评论并不适用于Control.BeginInvoke,但它适用于Delegate.BeginInvoke?你能给我提供一个解释这个的链接吗? - cornergraf
好的,谢谢。我确实知道MessagePump的一般情况,但我认为BeginInvoke/Invoke调用可能会因为某些特殊原因而具有特殊行为,所以我想要确定一下。 - cornergraf
你是正确的。问题是关于UI线程再次解除阻塞后会发生什么,哪个BeginInvoke/Invok调用将首先执行。 - cornergraf
我刚刚测试了一下,发现这个答案是错误的(如果有影响的话,我使用的是.NET 3.5)。Invoke调用可以在之前的BeginInvoke调用之前执行。 - mafu
在BeginInvoke MSDN文章的备注部分中提到:“如果在相同的DispatcherPriority下进行多个BeginInvoke调用,则它们将按照调用的顺序执行。” http://msdn.microsoft.com/en-us/library/ms591206(v=vs.110).aspx - Sergey Miryanov
显示剩余3条评论

3

BeginInvoke调用会在目标线程上排队(因为它们按到达顺序发布)。

WCF线程上的同步调用(步骤3)可能会在从该线程发出的异步调用(步骤2)之前执行。


好的,非常感谢。你有这个声明的来源吗?我已经尝试在谷歌上找到一些明确的东西,但迄今为止没有成功。 - cornergraf

0

没有足够的信息给你一个好的答案。UI线程被阻塞,所以步骤2和3必须在不同的线程上运行。如果两者之间没有同步,那么我们怎么知道任何顺序呢?

Thread 1        Thread 2                       Thread 3         Thread 4
Block UI        Calls BeginInvoke              
Unblock UI      Calls Invoke or BeginInvoke    BeginInvoke runs  BeginInvoke runs

你的程序中存在很多并行处理,但从你所描述的情况来看,我们无法确定可能发生的顺序,除了说“什么都有可能”。我们甚至不能确定调用BeginInvoke的时间是在UI线程被阻塞之前还是之后。


好的,步骤1-4的顺序是有保证按照这个顺序进行的。问题只在于是否这也会保证步骤3和4中的BeginInvoke/Invoke调用的执行顺序。我会更新问题以使其更加清晰明了。 - cornergraf
啊,修改了Control.BeginInvokeControl.Invoke的编辑确实改变了很多。很高兴有人能够为你解决这个问题。 :) - Greg D
是的,我又意识到在与他人讨论时往往会把某些信息视为理所当然。将来我会尽量更加准确。不过还是谢谢您的回复。 - cornergraf

0

你不能假设两个调用之间存在依赖关系,但如果它们之间确实有某种形式的依赖关系,则可以让它们等待信号量并仅在它们都完成时执行相关代码。

如果你同时进行这两个调用的原因不是为了提高性能,那么我可能会建议你在第一个回调函数中执行第二个调用(这样更容易调试)。


实际上,步骤3和4可能会交换,但如果它们交换了,我知道(显然)步骤2将首先执行。因此,我的问题只在执行顺序完全按照所呈现的方式时才相关,这就是为什么我用这种方式表达的原因。 - cornergraf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接