Help with objects

My project relies a lot on threading, So I use an object like this:



and I call it like this:


```cs
 
lock (CardLock)
                {
                    using (StreamReader r = new StreamReader(file))
                    {
                        int i = 0;
                        while (ReadLineEx(r) != null) { i++; }
                        return i;
                    }
                }
 

This way the SD card doesn’t try and get used at the same time by 2 or more threads.

I would like to turn on an LED every time I call this object to show that the card is in use. Is there an easy way to do this?

Thanks

You could probably work up something with Monitor.TryEnter in a separate thread, but you’d either eat up a likely-noticeable amount of CPU cycles, or it wouldn’t be very responsive, and you’d likely end up delaying some/all of your SD accesses while your extra thread checks to see if it can acquire a lock.

Turn the light on when you enter the lock, and turn it back off when you leave? ::slight_smile:

you have to be careful of a race condition with that solution.

The Monitor class in full .NET has methods for determining if a lock is being held. Unfortunately, MF does not have those methods.

I think a dual locking solution is going to be needed, if querying of the lock state is needed.

public class TryLockObject
{
	private bool locked = false;

	public TryLockObject()
	{
	}

	public bool TryLock()
	{
		lock(this)
		{
			if (locked)
				return false
			else
			{
				locked - true;
				return true;
			}
		}
	}
}

Freeing of the lock is left as a student exercise.

A further exercise would be handling multiple locks by the same thread.

@ stotech - Do you only want to turn the LED on when one or more threads are queued waiting for another thread to finish accessing the card, in other words to indicate that there is resource contention. Or are you wanting to turn the LED on every time you access the card regardless of whether there are queued threads waiting to access the card or not?

@ stotech - I decided to assume you wanted to just light up the LED if there was contention accessing the device. That was the more interesting problem :slight_smile:

I quickly put the code below together, I have not really tested it, but I think it would do the trick.


public delegate void CodeBlock();
public class ContendedLock
{
    private int _contentionCount;
    private object _syncBody = new object();
    private object _syncCallbacks = new object();
    private CodeBlock _onContended;
    private CodeBlock _onClearContended;

    public ContendedLock(CodeBlock onContended, CodeBlock onClearContended)
    {
        if (onContended == null) throw new ArgumentNullException("onContended");
        if (onClearContended == null) throw new ArgumentNullException("onClearContended");

        _onContended = onContended;
        _onClearContended = onClearContended;
    }

    public void Lock(CodeBlock body)
    {
        int currentCount = Interlocked.Increment(ref _contentionCount);
        try
        {
            if (currentCount == 2)
            {
                lock(_syncCallbacks)
                {
                    _onContended.Invoke();
                }
            }

            lock(_syncBody)
            {
                body.Invoke();
            }               
        }
        finally
        {
            currentCount = Interlocked.Decrement(ref _contentionCount);
            if (currentCount == 1)
            {
                lock(_syncCallbacks)
                {
                    _onClearContended.Invoke();
                }
            }
        }
    }
}

You can use this class to put a lock around a piece of code, but callback to another routine if the lock is already taken ie, another thread has the lock and your new thread is going to block waiting to enter the lock, this is where you could turn on the LED. Once the callback has executed the code proceeds to wait on the lock as usual. When there is no longer contention on the lock, the second callback is called to take action to indicate the contention has cleared ie. turn off the LED.

Using the class is as simple as the following

  1. Create an instance of the ContendedLock, passing the routine to be executed when contention is identified and when it clears up.

static ContendedLock myLock = new ContendedLock(
    // Code executed when there is contention, you can turn on the LED here
    () => Debug.Print("Contended"),
       
    // Code executed when there is no longer contention, you can turn the LED off here.   
    () => Debug.Print("Clear Contended") 
);

  1. Use the contended lock instance to guard the code that needs to be synchronized across threads

// Acquire the lock and execute the code, calling the constructor callbacks as appropriate
myLock.Lock(() =>
{
    // Run your code here, only one thread at a time will be able to execute this code
});

1 Like

Sorry about the late reply. Thanks for the help everyone. Especially @ taylorza. I’m can’t play with my toys at the moment cause I’m away. I think I’ll try that contended lock stuff though, the code is out of my depth, but I might learn something trying to implement it.

Thanks