-1

My situation is this:

  • I only have access to a part of the code that is already running in multithreading, so I'm not creating the threads and can not access the part of the code where the threads are being created
  • I need to ensure that a fairly complex (multiple functions are called, there is DB access involved, etc.) portion of code is executed exclusively by a single thread at a time

So my question is, it is possible to do that? and if that so, what is the best way to do it?

Here is some illustrative code of what I'm trying to acomplish:

// This method is executed by multiple threads at the same time
protected override void OnProcessItem()
{
    MyObject myObject = new MyObject();

    // Begin of the code that should be executed only once at a time
    // by each thread

    bool result = myObject.DoComplexStuff();

    if(result == true)
    {
        this.Logger.LogEvent("Write something to log");
        // ... Do more stuff
    }
    else
    {
        this.Logger.LogEvent("Write something else to log");
        // ... Do more stuff
    }

    // ... Do more stuff

    // End of the code that should be executed only once at a time
    // by each thread
}

Some background

Before asking here I did an small investigation effort and end reading this:

https://learn.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives

But still I'm not sure what's the best approach or how to implement it in mi scenario.

Additionally I'm no expert at multithreading as you may guess.

Manuel Navarro
  • 1,789
  • 2
  • 16
  • 18
  • 3
    Are you looking for `lock`? `lock (syncObject) {/* one thread at a time */}`? In your case it could be `lock (this.Logger) {...}` – Dmitry Bychenko Dec 28 '17 at 15:39
  • About the duplicated marking, I will say that the answer in the other post totally applies here, but the way the question is asked makes it difficult to find it if you are looking for this in a more general way. – Manuel Navarro Dec 29 '17 at 18:12

3 Answers3

2

The easiest way is to put lock, e.g.:

// static: conservative policy: no two threads in the entire application
// can enter locked block at the same time. 
// You may want to be more lenient and lock, say on this.Logger i.e. 
// no two theards addressing the same Logger... 
private static object syncObject = new object();

...

protected override void OnProcessItem() {
  MyObject myObject = new MyObject();

  // Begin of the code that should be executed only once at a time
  lock (syncObject) {
    bool result = myObject.DoComplexStuff();

    if (result) {
      this.Logger.LogEvent("Write something to log"); 

      // ... Do more stuff
    }
    else {
      this.Logger.LogEvent("Write something else to log");

      // ... Do more stuff
    }

    // ... Do more stuff
  } 
  // End of the code that should be executed only once at a time by each thread
} 
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
1

Yes, you can use lock for this. Create a private synchronization object in your class, acquire the lock on this object and only one thread at a time will be able to execute the code within the lock block.

class Foo
{ 
    private readonly object syncObj = new object();

     public void Blah()
     {
          lock (syncObj)
          {
              //only one thread at a time
              //will execute this code
          }
     }
 }
InBetween
  • 32,319
  • 3
  • 50
  • 90
  • I actually read about locks on objects, but never crossed my mind to create a dummy object for syncing, I just thought that to use the lock approach I required to have the necessity to lock just a single object. Thanks a lot. – Manuel Navarro Dec 29 '17 at 18:06
  • 2
    @ManuelNavarro You are welcome! One small comment: the code above ensures that the code inside the lock is executed by one thread at a time for *each instance of Foo*. If what you need is that the code can only be executed by one thread no matter what instance of `Foo` then you should make `syncObj` static. – InBetween Dec 29 '17 at 18:22
0

I've added some comments on how lock is working

private object _OnProcessItemLockObject = new object();
// This method is executed by multiple threads at the same time
protected override void OnProcessItem()
{
    MyObject myObject = new MyObject();

    // Begin of the code that should be executed only once at a time
    // by each thread

    bool result = false;
    lock(_OnProcessItemLockObject)
    {
        //mat: the part inside the lock will only be executed by one thread. All other threads will wait till the lock-object is unlocked.
        result = myObject.DoComplexStuff();
    }

    //mat: the following code will get executed parallel
    if(result == true)
    {
        this.Logger.LogEvent("Write something to log");
        // ... Do more stuff
    }
    else
    {
        this.Logger.LogEvent("Write something else to log");
        // ... Do more stuff
    }

    // ... Do more stuff

    // End of the code that should be executed only once at a time
    // by each thread
}
Mat
  • 1,960
  • 5
  • 25
  • 38