Tim B
Tim B

Reputation: 43

How to stop thread when Lock is encountered?

I have the following code that starts some threads:

    List<Stuff> lNewStuff = new List<Stuff>();

    // populate lNewStuff

    for (int i = 0; i < accounts.Length; i++)
    {
        Account aTemp = _lAccounts.Find(item => item.ID == accounts[i]);

        Thread tTemp = new Thread(() => aTemp.ExecuteMe(lNewStuff));
        tTemp.Start();     
    }

Then in the Account class you have the ExecuteMe method that has a lock:

    public class Account
    {
        private Object lockThis = new Object();

        public void ExecuteMe(List<Stuff> lNewStuff)
        {
            //Ensure only one thread at a time can run this code
            lock (lockThis)
            {
                //main code processing
            }
        }
    }

Now, sometimes the thread starts with lNewStuff == null since it sometimes does not find any New Stuff with the Account ID. This is normal for this project. The thread should always try to run but when null I want this thread to die and not wait when a lock is encountered.

So specifically:

If lNewStuff is null and there is a lock then terminate the thread. (how to do this?)

If lNewStuff is null and there is no lock then run normally (does this already)

If lNewStuff is not null and there is a lock then wait for the lock to finish (does this already)

if lNewStuff is not null and there is no lock then run normally (does this already)

Upvotes: 1

Views: 2080

Answers (3)

LukeH
LukeH

Reputation: 269328

When lNewStuff is null you could use Monitor.TryEnter and only continue if the lock is granted:

public class Account
{
    private readonly object lockThis = new object();

    public void ExecuteMe(List<Stuff> lNewStuff)
    {
        bool lockTaken = false;
        try
        {
            if (lNewStuff == null)
            {
                // non-blocking - only takes the lock if it's available
                Monitor.TryEnter(lockThis, ref lockTaken);
            }
            else
            {
                // blocking - equivalent to the standard lock statement
                Monitor.Enter(lockThis, ref lockTaken);
            }

            if (lockTaken)
            {
                // main code processing
            }
        }
        finally
        {
            if (lockTaken)
            {
                Monitor.Exit(lockThis);
            }
        }
    }
}

Upvotes: 3

JerKimball
JerKimball

Reputation: 16894

Just to be different:

public class Foo : IDisposable
{
    private Semaphore _blocker;
    public Foo(int maximumAllowed)
    {
        _blocker = new Semaphore(1,1);
    }

    public void Dispose()
    {
        if(_blocker != null)
        {
            _blocker.Dispose();
            _blocker.Close();
        }
    }

    public void LimitedSpaceAvailableActNow(object id)
    {
        var gotIn = _blocker.WaitOne(0);
        if(!gotIn)
        {
            Console.WriteLine("ID:{0} - No room!", id);
            return;
        }
        Console.WriteLine("ID:{0} - Got in! Taking a nap...", id);
        Thread.Sleep(1000);
        _blocker.Release();
    }
}

Test rig:

void Main()
{
    using(var foo = new Foo(1))
    {
        Enumerable.Range(0, 10)
            .Select(t => 
                Tuple.Create(t, new Thread(foo.LimitedSpaceAvailableActNow)))
            .ToList()
            .AsParallel()
            .ForAll(t => t.Item2.Start(t.Item1));
        Console.ReadLine();
    }
}

Output:

ID:4 - Got in! Taking a nap...
ID:8 - No room!
ID:0 - No room!
ID:7 - No room!
ID:2 - No room!
ID:6 - No room!
ID:5 - No room!
ID:9 - No room!
ID:1 - No room!
ID:3 - No room!

Upvotes: 0

TalentTuner
TalentTuner

Reputation: 17556

If lNewStuff is null and there is a lock then terminate the thread. (how to do this?) , 
do you want to still start a thread if lNewStuff is Null if answer is no then solution must be very simple.

List<Stuff> lNewStuff = new List<Stuff>();

// populate lNewStuff

for (int i = 0; i < accounts.Length; i++)
{
    Account aTemp = _lAccounts.Find(item => item.ID == accounts[i]);
   if(lNewStuff!=null)
   {
          Thread tTemp = new Thread(() => aTemp.ExecuteMe(lNewStuff));
          tTemp.Start();   
   }

}
also you shd create a single lock object 
private Object lockThis = new Object(); // this statement is creating new lock object with every account object, and hence does not ensure critical section protection.

Change this to

private static Object lockThis = new Object(); 

Upvotes: 0

Related Questions