所以,我收到以下代码的异常。我已经把它的异常细节,但我相信它是由一个不同的线程释放锁然后启动锁定的事实引起的。我希望这样做可能允许我的主线程在写入队列结束时继续。
首先,我想知道是否有办法可以做到这一点?其次,如果这样做或者这是一个糟糕的计划?看过ManualResetEvent,Monitor和Mutex所有这些似乎都是这样做的。请注意,这是针对网络服务器的,这是我第一次编写多线程,可能是高流量的服务器。
异常:第一次调用send(及其回调)时抛出。
mutex.ReleaseMutex()上的System.ApplicationException。 “从非同步的代码块调用了对象同步方法。”
public void SendAsync(byte[] packet)
{
mutex.WaitOne();
client.GetStream().BeginWrite(packet, 0, packet.Length, WriteCallback, null);
}
private void WriteCallback(IAsyncResult ar)
{
client.GetStream().EndWrite(ar);
mutex.ReleaseMutex();
Console.WriteLine("Sent Data to " + RemoteEndPoint);
}
答案 0 :(得分:3)
假设您正在使用Mutex类,根据Microsoft
Mutex类强制执行线程标识,因此互斥锁只能由获取它的线程释放。相比之下,Semaphore类不强制执行线程标识。互斥体也可以跨应用程序域边界传递。
我认为,你的回调方法是从另一个线程调用的,它会导致异常 正如Microsoft建议的那样,您可以在这种情况下使用Semaphore。
例如:
static volatile Semaphore sem = new Semaphore(1,1);
static void Main(string[] args)
{
Thread oThread = new Thread(new ThreadStart(fn2));
oThread.Start();
Thread.Sleep(200);
sem.WaitOne();
Console.WriteLine("Main is Doing");
Thread.Sleep(2000);
sem.Release();
}
static void fn2()
{
sem.WaitOne();
Console.WriteLine("Thread is Doing");
Thread.Sleep(2000);
sem.Release();
}
答案 1 :(得分:2)
考虑到这一点 -
我想这样做可能允许我的主线程在写入队列结束时继续。
首先,我想知道是否有办法可以做到这一点?
我认为你不需要mutex
。你在寻找这样的东西 -
static object _lock = new object(); //somewhere based on your context
public void SendAsync(byte[] packet)
{
Task.Run(() =>
{
..... other codes
lock (_lock)
{
client.GetStream().BeginWrite(packet, 0, packet.Length,
ar => // the write callback (lambda)
{
client.GetStream().EndWrite(ar);
Console.WriteLine("Sent Data to " + RemoteEndPoint);
}, null);
}
});
}
说明:
Task.Run
在线程池中异步运行,这样可以保持主线程一直空闲。lock(_lock)
确保在任何一个时刻只有一个线程正在写入流(线程由threadpool
Task.Run
生成writecallback
,您可以使用内联lambda callback
方法。让生活更轻松。如果这可以解决您的问题,请告诉我。