Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ensuring Thread Safety

I am in the midst of writing a C# Windows Form application that processes quotes from the market through an algorithm (strategy) to create orders to a brokerage firm. That all seems to be testing fairly well until I tried to build in the capacity to run multiple strategies simultaneously with each strategy on it's own thread. At this point everything starts running incorrectly. I believe I have some classes that are not thread safe which are driving erratic behavior. Any insight on how I can thread this in a thread safe manner is deeply appreciated!

The way the Quotes are fed into the Algorithms is as Follows: 1) Market Data Events are fired from Brokers Software to a client class in my Software called ConnectionStatus. When the market Data event is triggered, a Quote object is built from the current values of these static variables that represent Bid, ask, etc. Once the quote is built, I am endeavoring to send it into each of the Strategy Algorithms that are running. Here is the code I am using to do that:

 foreach (StrategyAssembler assembler in StrategyAssembleList.GetStrategies())
 {                  
     BackgroundWorker thread = strategyThreadPool.GetFreeThread();
     if (thread != null)
     {
        thread.DoWork += new DoWorkEventHandler(assembler.NewIncomingQuote);
        thread.RunWorkerAsync(quote);
     }   
 }

StrategyAssembler is a class that creates an instance of the Class StrategyManager which in turn creates an instance of the strategy that contains the actual algorithms. There may be 4 or 6 different instances of StrategyAssembler, each of which has been added to a Singleton instance of StrategyAssembleList which is a BindingList.

The incoming quote object is passed into the the NewIncomingQuote method of the StrategyAssembler Class. That code is as follows:

public void NewIncomingQuote(object sender, DoWorkEventArgs e)
    {
        Quote QUOTE = e.Argument as Quote;            

        lock (QuoteLocker)
        {
            manager.LiveQuote(QUOTE);

            priorQuote = QUOTE;
        }
    }

I was thinking that by using a lock before passing the quote into the manager.LiveQuote(Quote quote) method that all the objects that use the quote "downstream" of this point would be able to consume the quote in a thread safe fashion, but testing is showing otherwise. Is there a way I could put the each instance Of StrategyAssembler on its own thread that ensures that all the objects created by Strategy Assembler are thread safe and then feed the quote into StrategyAssembler? Is this path of thinking an appropriate way to deal with this situation?

Thanks in advance for any feedback or help,

Learning1

like image 900
Learning1 Avatar asked Mar 01 '10 19:03

Learning1


1 Answers

The locking should occur at both the reading and writing to any shared state. Without locks on the read, the code can still read and write concurrently.

You could wrap the read and write locking into the manager.

like image 169
spender Avatar answered Nov 07 '22 23:11

spender