【问题标题】:Synchronize a call that is either Invoked (through dispatcher) or called directly同步调用(通过调度程序)或直接调用的调用
【发布时间】:2011-07-27 20:28:14
【问题描述】:

是的,我现在正在为 GUI 编程。但是,我面临一个似乎无法自行解决的同步问题。

我正在通过 UDP 远程开始/停止视频播放。传入的代码/命令被解析,然后在 'Window' 类中执行。

由于它是一个 GUI 元素,任何对元素的调用都必须在创建它的线程上执行。不过,我的 UDP 客户端是在自己的线程上运行的。因此任何调用都需要通过 Dispatcher.Invoke 方法。

不过,这很好用。这有很多问题。例如,'load' 方法和 'play' 方法可以相互直接执行。这可能导致在“加载”方法之前执行“播放”方法。因为我无法控制何时对所述对象调用操作。

所以我想,我会在对象上使用监视器/互斥量/信号量/锁(),然后等待它再次被释放。请参见下面的代码 sn-ps。但这会导致异常:

调用 Exit、Pulse 会引发 SynchronizationLockException, 来自未同步的 Monitor 类的 PulseAll 和 Wait 方法 代码块。

所以我正在寻找一种更好/更有效的方式来同步两个线程。如果调用是通过dispatcher调用的,其他线程基本会等到被调用的方法调用完毕。

另外,如果我使用了错误的术语,请原谅我的措辞。

派送方式:

#region ExecuteDispatch Members
public void Dispatch(Callback call)
{
    Dispatch(this, call);
}
public void Dispatch(DispatcherObject o, Callback call)
{
    if (!o.Dispatcher.CheckAccess())
    {
        o.Dispatcher.Invoke(
            System.Windows.Threading.DispatcherPriority.Send,
            new Action(call)
        );
    }
    else
    {
        call();
    }
}
#endregion

应该“同步”的方法:

Monitor.Enter(player);
Dispatch(delegate()
{
    player.Stop();
    Monitor.Exit(player);
});
Monitor.Enter(player);
Monitor.Exit(player);

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    一种可能的方法是让一个线程向另一个线程发出信号,表明他完成了工作。因此,您可以使用 AutoResetEvent 或 ManualResetEvent:

    AutoResetEvent evt = new AutoResetEvent(false);
    
    Dispatch(delegate()
    {
        player.Stop();
        evt.Set();
    });
    
    evt.WaitOne(); //Here the thread waits until Set is called on evt
    

    【讨论】:

    • 这似乎可以满足我的需要。我会再等一会儿再弹出其他答案,否则这个答案会被接受
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2020-10-10
    • 2011-09-09
    • 1970-01-01
    相关资源
    最近更新 更多