C# Multithreading Synchronisation

Welshy said:
Hopefully my final question, but what would be the best way to pass the Plane to the next section? As the array of Sections is a member in the MainWindow class, the Plane threads cannot access it directly. Passing the entire array into each plane seems a bit like overkill, maybe use a delegate to collect and return the next Section? Pretty much as I had before.
You'd probably want each section of tarmac to contain an array/list of tarmac sections that it's linked to. That way the plane's thread only has to look at a certain member of the current tarmac section to find the next section.
 
Woo I've got them going round happily, and queuing as they should :D

Using a slightly modified version of the method Lagz provided. Added a very basic queue mechanism to it, which is no doubt going to get ripped apart as soon as I post this :p

Code:
        public void lockRunway(ref Plane iPlane)
        {
            lock (this)
            {
                while (mQueue)
                {
                    Monitor.Wait(this);
                }

                while (mPlane != null)
                {
                    mQueue = true;
                    //The runway section is in use
                    //by another plane, so block on
                    //this object.
                    Monitor.Wait(this);
                }
                //We have acquired the runway :-)!
                mPlane = iPlane;

                mQueue = false;
            }
        }

Can't thank you guys enough for the help :)
 
The only problem is that you only allow one plane to queue. Any other planes which arrive when one plane is already queuing essentially just have a free for all to decide who gets to go next, presumably you know this :-).

You can implement a full queue like this (this is a more generic first come first serve lock, but could be adapted easily).

Code:
    public class FCFS
    {
        private List<Thread> mQueue = new List<Thread>();

        public FCFS()
        {
        }

        public void enter()
        {
            Thread mThreadToQueue = Thread.CurrentThread;

            try
            {
                lock (mQueue)
                {
                    //queue the thread
                    mQueue.Add(mThreadToQueue);
                }

                lock (mThreadToQueue)
                {
                    if (mQueue[0] != mThreadToQueue)
                    {
                        //take out its lock and block the thread on itself
                        Monitor.Wait(mThreadToQueue);
                    }
                }
            }

            //If we reach here then we are the front of the queue - so we have acquired the lock :-)!

            //if the thread is interrupted remove it from the list
            catch (ThreadInterruptedException lExc)
            {
                mQueue.Remove(mThreadToQueue);
                throw lExc;
            }
        }

        public void exit()
        {
            mQueue.RemoveAt(0); //remove the thread just processed

            if (mQueue.Count > 0)
            {
                //There is another thread waiting. . .
                Thread lNext = mQueue[0];
                lock (lNext)
                {
                    //Wake it up
                    Monitor.Pulse(lNext);
                }
            }
        }
    }

Obviously this is much more complex than the simple version. It seems to work, although I am not certain that it is thread safe. I cant see anything wrong with it, but its a pretty complex peice of synchronization code so I could be wrong :-)!
 
Welshy said:

Because when you pass an Object you are already actually passing a reference. I'm not sure what exactly happens when you explicitly use ref as well. Presumably you pass a reference to a reference, which is a little strange?! In any case I cant think why you would want to use it.

*I dont really know anything about it - but I'm pretty sure you shouldn't do this :-). In any case it isn't necessary*
 
Last edited:
Welshy said:
Well because you don't need to, I can only assume that you believe the ref keyword is used to pass the object reference and not a copy of the object? This is untrue, in C# classes are always handled by ref, types such as structs, int, bool etc are all passed by value.

Passing a reference using ref means that the pointer to the object can be re assigned to another object and that change will be reflected back in the original calling code. Won't break the code not having it but it's not good code practise :)
 
Oh right, I'm more used to writing in C++ and needing to pass references :p

Lagz - the queue is as simple as it is, because no more than two planes can be queuing for the same section anyway, so no need :)

edit: for future reference, if i pass "this" into a method, is that also a reference? or have i passed by value?
 
Welshy said:
Oh right, I'm more used to writing in C++ and needing to pass references :p

Lagz - the queue is as simple as it is, because no more than two planes can be queuing for the same section anyway, so no need :)

edit: for future reference, if i pass "this" into a method, is that also a reference? or have i passed by value?

Reference
 
Welshy said:
Oh right, I'm more used to writing in C++ and needing to pass references :p

Lagz - the queue is as simple as it is, because no more than two planes can be queuing for the same section anyway, so no need :)

edit: for future reference, if i pass "this" into a method, is that also a reference? or have i passed by value?

Well, to be exact, you're passing a reference to the current object, if using "ref", then the object reference is itself passed by reference, so changes to the object reference inside the callee will be reflected back in the caller (just like for any other variable), otherwise by value, so changes to the reference inside the callee will be lost. A reference (or pointer if you like) is itself a value type.

Consider the following code:
Code:
using System;
using System.Collections.Generic;
using System.Text;

namespace PassObjectByRefOrValu
{
    class FooBar
    {
        public string identity;
        public FooBar(string identity) { this.identity = identity; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            p.Run();
        }

        private void Run()
        {
            FooBar foo = new FooBar("foo");

            PassReferenceByValue(foo);
            Console.WriteLine("foo.identity = '" + foo.identity + "' after call to PassReferenceByValue().");
            // outputs "foo" as the foo object reference here still points to the object created above.

            PassReferenceByReference(ref foo);
            Console.WriteLine("foo.identity = '" + foo.identity + "' after call to PassReferenceByReference().");
            // outputs "bar" as the foo object reference here now points to the new object created inside PassReferenceByReference() due to the ref keyword. 

            Console.ReadLine();
        }

        private void PassReferenceByValue(FooBar objrefByValue) {
            objrefByValue = new FooBar("bar");
        }
        private void PassReferenceByReference(ref FooBar objrefByReference)
        {
            objrefByReference = new FooBar("bar");
        }
    }
}
 
Back
Top Bottom