在Silverlight中,为了调用UI线程,我们应该使用this.Dispatcher.BeginInvoke((ThreadStart)delegate(){})
。
我的问题是,如果多个线程调用一个执行此操作的函数,那么这些调用是否排队并一个接一个地执行?如果是,那么我可以安全地假设即使从多个线程调用该函数,this.Dispatcher.BeginInvoke((ThreadStart)delegate(){} );
内的代码也是线程安全的吗?
答案 0 :(得分:3)
代码在没有状态时是线程安全的,不修改可以跨线程边界共享的状态,或者以受控方式修改状态,使该状态的所有用户共享以确保线程安全(例如锁定) )。
因此,Dispatcher.BeginInvoke
无法保证线程安全。也就是说,保证代理将在同一个线程(UI线程)上执行,因此您可以假设代理不会同时运行。这并不意味着它们本身就是线程安全的 - 这取决于你在这些委托中做了什么 - 但是如果你不旋转或与那些委托调用的那些委托或方法中的其他线程交互,你可以假设线程安全。
答案 1 :(得分:1)
由于使用了(ThreadStart)委托类型,您的代码段有点误导。需要知道的重要一点是,在任何STA Threaded环境中,只有一个线程可以成为“UI”线程。需要在该线程上创建并交互所有UI对象。
因此Dispatcher用于几个最容易理解的用法是从后台线程使用它来将你正在调用的内容放回UI线程。所以你放在那里的并不是“线程安全”,但保证在UI线程上调用它。如果你将你所做的一切都放到UI线程上,它将被一个接一个地调用,而不是同时调用。
BeginInvoke是一个异步调用,用于将委托放在UI线程队列上,而Invoke是同步调用。令人难以置信的是,您实际上可以从UI线程调用Invoke,它将阻塞,将您的委托放入队列并屈服于队列中的下一个项目,最终调用它刚刚调用的内容。
要记住的另一个重要事项是Dispatcher实际上是一个优先级排队。因此,在先进先出的意义上,它不是纯队列,因为您插入队列的位置取决于您的优先级,并且完全有可能将足够的东西塞进队列中,您的调用方法永远不会被执行
答案 2 :(得分:0)
是的,这些电话排队等候。对BeginInvoke
的调用是线程安全的(您可以随时从任何线程调用此方法),并且所有调用到UI线程的调用都运行单线程。因为只有一个UI线程。因为
答案 3 :(得分:0)
通常,是的,您是正确的,每个委托都被添加到队列中以等待Dispatcher线程的处理。
我不确定在从Dispatcher.BeginInvoke()调用调用委托时是否有任何当前或未来的保证 - 但我知道目前的顺序似乎仍然存在。
尽管如此 - 是的,可以安全地假设只有Dispatcher(UI)线程 - 因此不会同时调用多个委托。