Multi Threading Concerns

time to read 17 min | 3383 words

ThreadSafeQueue is a nice way to handle multi threading, but I needed something more.

I want to use this to speed up UI responsiveness, so this means that I need some way to test whatever an object exist in the queue without waiting (that would defeat the whole point, wouldn't it?).

I wanted to be able to do something like:

object o;

do

{

      o = q.TryDequeue();

      UpdateWaitUI();

}while(o == null);

DisplayObject((StronglyTypedObject)o);

Here are my additions to the class:

Test:

#region TryDequeueWithWorkerThreadsReturnSameNumberOnItems

 

[Test]

public void TryDequeueWithWorkerThreadsReturnSameNumberOnItems()

{

      int objectCount=0, createdObjects= 100;

      ThreadStart ts = new ThreadStart(TryDeuqueWorkerThread);

      Thread first = new Thread(ts),second = new Thread(ts);

      first.Start();

      second.Start();

      for (int i = 0; i < createdObjects; i++)

      {

            q.Enqueue(new object());

      }

      runThread = false;

      first.Join();

      second.Join();

      while(q.TryDequeue()!=null)

            objectCount++;

      Assert.AreEqual(createdObjects,objectCount,"Got a different amount of objects than those created");

}

 

private void TryDeuqueWorkerThread()

{

      object o;

      while(runThread)

      {

            o = q.TryDequeue();

            if(o!=null)

                  itemsQueue.Enqueue(o);

      }

}

 

#endregion

Code:

/// <summary>

/// Resets the event if needed.

/// Only called when we have lock!

/// </summary>

private void ResetEventIfNeeded()

{

      if (q.Count == 0)

            newItemEntered.Reset();

}

 

public object TryDequeue()

{

      if (q.Count > 0)

      {

            lock (this)

            {

                  if (q.Count > 0)

                  {

                        object result = q.Dequeue();

                        ResetEventIfNeeded();

                        return result;

                  }

            }

      }

      return null;

}