Synchronized methods in C#
Asked Answered
B

2

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#?

Brisbane answered 22/2, 2013 at 15:28 Comment(4)
Related: #541694Thine
@stigok not related, it's a duplicateIslamite
Not duplicate, they did not mention wait() and notifyAll()Brisbane
@Dimme, regarding 'it should be safe for threads to write and read messages to and from it' see if BlockingCollection<T> fits what you need. Also, you can have a look at Concurrent CollectionsBebeeru
A
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
    }
}
Amazement answered 22/2, 2013 at 15:32 Comment(4)
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.Dittmer
I agree with @MatthewWatson. You should avoid MethodImplOptions.Synchronized and instead use explicit locks.Mariammarian
The question was how to achieve this in C#, not what would be more likable.Amazement
Answers on StackOverflow often include the concept of "best practice" as well as just simply "would work"...Dittmer
T
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.

Trichology answered 22/2, 2013 at 15:33 Comment(2)
Could ManualResetEvent be substituted for a Mutex semaphore?Brisbane
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.Trichology
A
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
    }
}
Amazement answered 22/2, 2013 at 15:32 Comment(4)
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.Dittmer
I agree with @MatthewWatson. You should avoid MethodImplOptions.Synchronized and instead use explicit locks.Mariammarian
The question was how to achieve this in C#, not what would be more likable.Amazement
Answers on StackOverflow often include the concept of "best practice" as well as just simply "would work"...Dittmer

© 2022 - 2024 — McMap. All rights reserved.