C# Queue

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Dave750
    New Member
    • Sep 2011
    • 9

    C# Queue

    I am very new to C# and am writing a program that needs a Form with some controls and 2 other separate threads that run continuously and talk to each other.

    this example has worked really well for me in a similar application in Python in the past and I understand it well, so I would like to bring it over to C# if possible. I am stuck at how to share the q object between the two classes. Can anyone point me in the right direction?
    Code:
    #very over simplified and abridged Python example
    q = Queue.Queue(100)
    
    class c1:
        def __init__(self, q):
            while 1:
                do stuff and add result to queue...
                q.put("data")
    
    class c2:
        def __init__(self, q):
            while 1:
                q.get()
                do other stuff after taking from queue...
    
    threada = c1(q)
    threadb = c2(q)
    threada.start()
    threadb.start()
  • Samuel Jones
    New Member
    • Jan 2011
    • 48

    #2
    The simplest way I can see how to do it is as follows.

    Code:
    static class globalvar {
        q = Queue.Queue(100)
    }
    To reference it use
    Code:
    globalvar.q
    And to tidy it up a little, put your subroutines (while, if, class, etc.) within '{' and '}'.

    Hope that helps.

    Comment

    • Joseph Martell
      Recognized Expert New Member
      • Jan 2010
      • 198

      #3
      In a very simple system a global queue object is fine, but I think it is generally advisable to avoid a global state.

      If you are looking to move your logic to C# you may want to take a look at a publish/subscription pattern or an observer pattern.

      It is easiest to avoid race conditions or other thread problems if someone owns the queue and controls access to adding or removing items. For this example, I am going to give the queue to the processing thread. The following code example is not tested so there may be problems, but it should give you enough info to get started:

      Code:
          public class Processor
          {
              private System.Collections.Queue _processQueue = new System.Collections.Queue();
              public void AddProcessItem(object o)
              {
                  if (o != null)
                  {
                      lock (_processQueue)
                      {
                          _processQueue.Enqueue(o);
                      }
                  }
              }
      
              public void ProcessQueue()
              {
                  Object processObject = null;
                  while (true)
                  {
                      if (_processQueue.Count > 0)
                      {
                          lock (_processQueue)
                          {
                              processObject = _processQueue.Dequeue();
                          }
      
                          //do processing
                      }
                  }
              }
          }
      By moving the queue inside a class you are limiting access to the queue object and therefore limiting potential threading problems.

      To add items to the queue, another class is defined that takes a reference to a processor object. This reference is the "subscripti on" part of the pattern mentioned above. The reference creates a link between the two objects so information can be passed to the processing thread:
      Code:
          public class Adder
          {
              private Processor _p = null;
              public Adder(Processor p)
              {
                  if (p == null)
                  {
                      throw new System.ArgumentNullException();
                  }
                  _p = p;
              }
      
              public void DoStuff()
              {
                  while (true)
                  {
                      //do a bunch of stuff...add item to process queue
                      _p.AddProcessItem(new object());
                  }
              }
          }
      The key here is that one object owns the queue and controls how the queue is accessed. This prevents race conditions and any other threading problems that may come up otherwise. The thread that adds items to the queue gets a reference to the object that owns the queue. All adding to the queue is taken care of by the owning object, again avoiding threading problems.

      This model does allow you to add some flexibility to your system if you choose. For example: You can have multiple processing objects and multiple adding objects. The adding objects can be dynamically assigned a queue so you can change who processes items dynamically.

      This code example does leave out some fairly large details like how the processing object monitors the queue. It really should not be in a constant loop like shown above. You can do something as simple as schedule a timer to periodically trigger processing of the queue or add more complex logic to trigger the processing method whenever an item is added to the queue. Other experts that have a lot of experience with this pattern may be able to offer better advice on how to overcome that particular challenge.

      Hope this helps.

      Comment

      Working...