C# 等待异步方法以C结尾#
示例代码:C# 等待异步方法以C结尾#,c#,multithreading,thread-safety,monitor,C#,Multithreading,Thread Safety,Monitor,示例代码: class Program { static readonly object locker = new object(); static void Main(string[] args) { Func(); Func(); Thread.Sleep(6000); } static void Func() { Monitor.Enter(locker);
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抛出异常
从未同步的代码块调用了对象同步方法
这里的错误是什么?实现这一点的首选方法是什么?我认为您可以使用等待事件完成。对不起,我对显示器没有任何经验。但是我正在使用ManualResetEvent/AutoResetEvent类来测试回调。我认为您可以使用来等待事件完成。对不起,我对显示器没有任何经验。但是我使用ManualResetEvent/AutoResetEvent类来测试回调。线程不能关闭监视器
Monitor.Exit(locker);
这是一个问题,线程不能关闭监视器
Monitor.Exit(locker);
这是一个问题
监视器。输入
和监视器。必须在同一线程上进行退出
调用。在示例中,您可以调用Monitor。在UI线程上输入,然后在为BeginInvoke
触发的异步调用创建的线程上退出
如果要等待异步操作在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);
}
}
然而,在您的场景中,您可以同步调用委托。Monitor.Enter
和Monitor.Exit
调用必须在同一线程上进行。在示例中,您可以调用Monitor。在UI线程上输入,然后在为BeginInvoke
触发的异步调用创建的线程上退出
如果要等待异步操作在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);
}
}
然而,在您的场景中,您可以同步调用委托。Monitor.Enter(locker)位于当前线程上,Monitor.Exit位于从当前线程调用的不同线程上。
因此,您还需要使用Monitor.Wait和Monitor.Pulse,但手动重置事件在您的情况下更容易。Monitor.Enter(locker)在当前线程上,Monitor.Exit在从当前线程调用时在不同的线程上。
因此,您还需要使用Monitor.Wait和Monitor.Pulse,但手动重置事件在您的情况下更容易发生。此错误非常容易误导。它实际上并不意味着它看起来意味着什么。实际上,这意味着在对同步对象调用Monitor.Enter
之前,会调用Monitor.Exit
您的监视器.Exit
调用发生在与监视器不同的线程上。Enter
调用--这两个调用看不到对方的同步对象。此错误非常容易引起误解。它实际上并不意味着它看起来意味着什么。实际上,这意味着在对同步对象调用Monitor.Enter
之前,会调用Monitor.Exit
您的监视器.Exit
调用发生在与监视器不同的线程上。Enter
调用--这两个线程看不到彼此的同步对象。如果您想在继续之前等待它完成,为什么要执行异步?代码可能不能代表实际问题:)从Main方法调用它的方式不正确它在现实生活中的使用方式。如果你想在继续之前等待它完成,为什么要执行异步?代码可能无法代表实际问题:)从主方法调用它的方式与现实生活中使用它的方式不同。