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);
}

      

+3


source to share


2 answers


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 using threadpool

    from Task.Run

    )
  • You don't need a separate one writecallback

    , you can use inline methods lambda callback

    . Makes life so much easier.

Let me know if this solves your problem.

+2


source


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();
    }

      

+2


source







All Articles