8

Part of porting a Java application to C# is to implement a synchronized message buffer in C#. By synchronized I mean that it should be safe for threads to write and read messages to and from it.

In Java this can be solved using synchronized methods and wait() and notifyAll().

Example:

public class MessageBuffer {
    // Shared resources up here

    public MessageBuffer() {
        // Initiating the shared resources
    }

    public synchronized void post(Object obj) {
        // Do stuff
        wait();
        // Do more stuff
        notifyAll();
        // Do even more stuff
    }

    public synchronized Object fetch() {
        // Do stuff
        wait();
        // Do more stuff
        notifyAll();
        // Do even more stuff and return the object
    }
}

How can I achieve something similar in C#?

dimme
  • 4,393
  • 4
  • 31
  • 51
  • 1
    Related: http://stackoverflow.com/questions/541194/c-sharp-version-of-javas-synchronized-keyword – sshow Feb 22 '13 at 15:31
  • @stigok not related, it's a duplicate – Luiggi Mendoza Feb 22 '13 at 15:35
  • Not duplicate, they did not mention wait() and notifyAll() – dimme Feb 22 '13 at 15:40
  • @Dimme, regarding 'it should be safe for threads to write and read messages to and from it' see if [BlockingCollection](http://msdn.microsoft.com/en-us/library/dd997371.aspx) fits what you need. Also, you can have a look at [Concurrent Collections](http://msdn.microsoft.com/en-us/library/dd287108.aspx) – publicgk Feb 22 '13 at 16:07

2 Answers2

7

In .NET you can use the lock-statement like in

object oLock = new object();
lock(oLock){
  //do your stuff here
}

What you are looking for are mutexes or events. You can use the ManualResetEvent-class and make a thread wait via

ManualResetEvent mre = new ManualResetEvent(false);
...
mre.WaitOne();

The other thread eventually calls

mre.Set();

to signal the other thread that it can continue.

Look here.

bash.d
  • 13,029
  • 3
  • 29
  • 42
  • Could `ManualResetEvent` be substituted for a `Mutex` semaphore? – dimme Feb 22 '13 at 16:02
  • 1
    Yes, but you would need two of those. One for signaling each thread. In the manner, when thread one created an object to signal this and the second to signal that the object has been consumed. Of course, if you'll want to many objects to be created, you'll might chose a different approach. It depends on the situation. But Events suit quite many situations. Please see the documentation on [MSDN](http://msdn.microsoft.com/en-us/library/ms173179.aspx). – bash.d Feb 22 '13 at 16:05
3

Try this:

using System.Runtime.CompilerServices;
using System.Threading;

public class MessageBuffer
{
    // Shared resources up here

    public MessageBuffer()
    {
        // Initiating the shared resources
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public virtual void post(object obj)
    {
        // Do stuff
        Monitor.Wait(this);
        // Do more stuff
        Monitor.PulseAll(this);
        // Do even more stuff
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    public virtual object fetch()
    {
        // Do stuff
        Monitor.Wait(this);
        // Do more stuff
        Monitor.PulseAll(this);
        // Do even more stuff and return the object
    }
}
Dave Doknjas
  • 6,394
  • 1
  • 15
  • 28
  • 3
    I don't like using MethodImplOptions.Synchronized because it does the equivalent of "lock this" for each method. And "lock this" is considered a bit dodgy because it increases the possibilities of deadlock. – Matthew Watson Feb 22 '13 at 15:35
  • 1
    I agree with @MatthewWatson. You should avoid MethodImplOptions.Synchronized and instead use explicit locks. – Patrik Svensson Feb 22 '13 at 15:41
  • The question was how to achieve this in C#, not what would be more likable. – Dave Doknjas Feb 22 '13 at 15:45
  • 1
    Answers on StackOverflow often include the concept of "best practice" as well as just simply "would work"... – Matthew Watson Feb 23 '13 at 16:58