Mutex over streams?
So I am getting an exception from the code below. I put the exception data with it, but I believe it has something to do with another thread releasing the lock and then the one that triggers the lock. I want to do this to potentially allow my main thread to continue while the write queue is in progress.
First of all, I want to know if this can be done? Second, should it be done or is it a bad plan? looked at ManualResetEvent, Monitor and Mutex, all of which seem to do this. Note that this is for a networked server and this is my first time writing multi-threaded, potentially high traffic.
Exception: Thrown the first time the send (and its callback) is called.
System.ApplicationException on mutex.ReleaseMutex (). "The object synchronization method was called from an unsynchronized block of code."
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);
}
source to share
Considering this -
I want to do this to potentially allow my main thread to continue while the write queue is in progress.
First of all, I want to know if this can be done?
I don't think you need it for that mutex
. Are you looking for something like this -
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);
}
});
}
Explanation:
-
Task.Run
runs asynchronously on a thread pool which keeps your main thread free all the time. -
lock(_lock)
ensures that only one stream is written to the stream at any given time (streams are created usingthreadpool
fromTask.Run
) - You don't need a separate one
writecallback
, you can use inline methodslambda callback
. Makes life so much easier.
Let me know if this solves your problem.
source to share
Assuming you are using the Mutex class, as per Microsoft
The Mutex class provides thread identification, so a mutex can only be released by the thread that acquired it. In contrast, the Semaphore class does not provide thread identity. A mutex can also be transferred across application domain boundaries.
I think your callback method is being called from another thread, it throws an exception.
As suggested by Microsoft, you can use Semaphore for this situation.
For example:
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();
}
source to share