Link to home
Start Free TrialLog in
Avatar of mcs26
mcs26

asked on

C# Multi Threading & Locking

Hi,

I have a Security object that contains two variables of type List<Price>, called CurrentPrices and NextPrices.

The security object loops through the CurrentPrices variable doing various calculations. Whilst this is being done I plan to use the ThreadPool to populate the NextPrices with data from a database.

Once the security object has finished looping through the CurrentPrices variable I copy the data from NextPrices to CurrentPrices and then NextPrices will again populate itself with fresh data whislt the security object loops through the CurrentPrices variable.

My question is how do I make sure that NextPrices has finished running before I copy its data to CurrentPrices. Please see the code below, I have stripped out some of the code to make it easier to follow as its not written to well as you can see!

Any help would be great,
Thanks,
M


public class Security
        {
            private delegate void delMultiThreadTP(Object Obj);
            private delMultiThreadTP delMultiTP;
            private int _LookBack;
            private AccessDataBank _Database;
            private ManualResetEvent _donePrice;
            private ManualResetEvent _doneFXPair;
            private DateTime _dtStart, _dtEnd;                        
            private SecurityTimeFrame[] _SecTP;
            private List<Price> _PricesNext = new List<Price>();
            private List<Price> Prices = new List<Price>();
            private string _Name;
            public string Signal{get;set;}

            private void RunTimePeriod(Object Obj)
            {
                ManualResetEvent[] doneTP = new ManualResetEvent[_SecTP.Length];

                // run through all the time periods
                for (int i = 0; i <= _SecTP.Length; i++)
                {
                    doneTP[i] = new ManualResetEvent(false);
                    _SecTP[i].RunTimePeriodSetup(doneTP[i]);
                    ThreadPool.QueueUserWorkItem(_SecTP[i].RunIndicatorDelegate, Prices);
                }

                WaitHandle.WaitAll(doneTP);

                // remove price oldest price element
                Prices.RemoveAt(0);
                
                // maybe i should be using an event here?
                if (CopyNextPriceList() == true)
                {
                    // need to copy prices over & then get next batch of prices
                    CopyPricesOver();
                   // start a new thread and repopulate _PricesNext using the GetPrices method below
                }

                _doneFXPair.Set();
            }

            private Boolean CopyNextPriceList()
            {
                Boolean Copy = false;
                if (Prices.Count < _LookBack)
                    Copy = true;                
                return Copy;
            }

            private void CopyPricesOver()
            {
                // Guessing I need to have some lock here??
                Prices.Clear();
                Prices.AddRange(_PricesNext.ToArray());
                _PricesNext.Clear();
            }

            private void GetPrices()
            {
                  _PricesNext = _Database.PriceData(_Name, _dtStart, _dtEnd);
            }
        }

Open in new window


        public class Price
        {
            public DateTime dtDTime;
            public double BidOpen, BidHigh, BidLow, BidClose;
            public double AskOpen, AskHigh, AskLow, AskClose;
            public double MidOpen, MidHigh, MidLow, MidClose;
        }

Open in new window

Avatar of kaufmed
kaufmed
Flag of United States of America image

Unless I am completely overlooking something, it appears that your code will wait before the other code is run.

You are queuing items to the ThreadPool in line 25, but once you break out of the loop, the very next instruction is to wait. The call to copy (the method in which you have a note about locking) does not come until a few lines later.

Is your code not functioning as you expect?
Yes, anyways you are setting your value after that so it should work. Let me give some time I will write the logic for your requirement.
Yes, I agree. Your code waits for all threads to complete. You then remove the first element from the Prices list (is this a debug thing? I don't quite see the point of that line) before copying the nextPrice list into the currentPrice list.

So your question is really answered by your code. You are already ensuring that you don't copy the NextPrices list into the currentPrices list before processing.

Is there a reason you process prices in a list? I mean do you do some kind of cumulative or averaging functionality on the list as a whole? If so, what determines the number of entries in the list that you populate from the database?
Avatar of mcs26
mcs26

ASKER

Hi,

Thanks for the replies. Firstly apologies for the code I posted (apart from being a mess) it is not complete and has probably not helped.

I thought by having two variables of type MannualResetEvent[], for example doneTP & doneSomethingElse & the line WaitHandle.WaitAll(doneTP) that the waithandle would only wait for all the doneTP to be set and carry on with the rest of the code - whilst the the thread assoicted with doneSomethingElse continues to pull data. Is my understanding completely wrong?

Cheers,
M
ASKER CERTIFIED SOLUTION
Avatar of kaufmed
kaufmed
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial