样本代码:
class Program
{
static readonly object locker = new object();
static void Main(string[] args)
{
Func();
Func();
Thread.Sleep(6000);
}
static void Func()
{
Monitor.Enter(locker);
Action act = () =>
{
Thread.Sleep(2000);
};
act.BeginInvoke(a =>
{
Console.WriteLine("exiting..");
Monitor.Exit(locker);
}, null);
Console.WriteLine("Func done...");
}
}理想情况下,控制台将打印出来:
Func done...
exiting...
Func done...
exitting...但是,我得到了:
Func done...
Func done...
exitting...然后Monitor.Exit抛出异常
对象同步方法是从不同步的代码块调用的。
这里的错误是什么?实现这一目标的首选方法是什么?
发布于 2011-03-30 08:15:17
Monitor.Enter(锁存器)位于当前线程上,Monitor.Exit位于另一个线程上,因为它是从当前线程调用的。
因此,您也需要使用Monitor.Wait和Monitor.Pulse,但ManualResetEvents在您的情况下更容易使用。
发布于 2011-03-30 08:15:01
Monitor.Enter和Monitor.Exit调用必须在同一个线程上进行。在您的示例中,您在UI线程上调用Monitor.Enter,在为BeginInvoke触发的异步调用创建的线程上调用Monitor.Exit。
如果您想在Func中等待异步操作完成,您可以这样做:
class Program
{
static void Main(string[] args)
{
Func();
Func();
Thread.Sleep(6000);
}
static void Func()
{
Action act = () =>
{
Thread.Sleep(2000);
};
IAsyncResult actAsyncResult = act.BeginInvoke(a =>
{
Console.WriteLine("exiting..");
}, null);
Console.WriteLine("Func done...");
act.EndInvoke(actAsyncResult);
}
}不过,在您的场景中,您只需同步调用委托即可。
发布于 2011-03-30 08:08:35
我认为您可以使用ManualResetEvent类等待事件的完成。对不起,我对Monitor没有任何经验。但是我使用ManualResetEvent / AutoResetEvent类来测试回调。
https://stackoverflow.com/questions/5483575
复制相似问题