-1

I'm using threading tasks to help speed up a portion of my program that is very slow but I'm getting an exception for the above and I can't seem to find where I'm handling the thread incorrectly that would cause this error to appear. I'm getting the error on the line that I made bold below. I also pasted my full stacktrace as well.

static void Main(string[] args)
    {
        OoplesFinanceDBModel model = new OoplesFinanceDBModel();

        // if there are no portfolios then create the first group
        if (model.Portfolios.Count() == 0)
        {
            initializePortfolios(model);
        }

        while (true)
        {
            // run through each symbol in each portfolio and see if it has surpassed it's goal
            // if so then sell it and choose a new stock to take its place
            foreach (Transactions transaction in model.Transactions.Where(i => i.TransactionType == "Buy" && i.Symbol == i.Symbol))
            {
                Console.WriteLine(transaction.Symbol);
            }
        }
    }

    public static void initializePortfolios(OoplesFinanceDBModel model)
    {
        try
        {
            // create one portfolio for each type of risk
            // each portfolio gets 4000 to start
            // 2000 cash and 2000 margin trading
            Portfolios lowrisk = new Portfolios();
            lowrisk.CreatedOn = DateTime.Now;
            lowrisk.CurrentCash = 2000;
            lowrisk.CurrentMargin = 2000;
            lowrisk.Name = "LowRiskTest1";
            lowrisk.TotalGainLoss = 0;
            lowrisk.TransactionCount = 0;
            lowrisk.UpdatedOn = DateTime.Now;

            Portfolios mediumrisk = new Portfolios();
            mediumrisk.CreatedOn = DateTime.Now;
            mediumrisk.CurrentCash = 2000;
            mediumrisk.CurrentMargin = 2000;
            mediumrisk.Name = "MediumRiskTest1";
            mediumrisk.TotalGainLoss = 0;
            mediumrisk.TransactionCount = 0;
            mediumrisk.UpdatedOn = DateTime.Now;

            Portfolios highrisk = new Portfolios();
            highrisk.CreatedOn = DateTime.Now;
            highrisk.CurrentCash = 2000;
            highrisk.CurrentMargin = 2000;
            highrisk.Name = "HighRiskTest1";
            highrisk.TotalGainLoss = 0;
            highrisk.TransactionCount = 0;
            highrisk.UpdatedOn = DateTime.Now;

            model.Portfolios.AddRange(new List<Portfolios>() { lowrisk, mediumrisk, highrisk });
            model.SaveChanges();

            List<Task> taskList = new List<Task>();

            // do low risk
            Task lowRisk = Task.Factory.StartNew(() => createTransactions(lowrisk.Name, "low", model));
            Task mediumRisk = Task.Factory.StartNew(() => createTransactions(mediumrisk.Name, "medium", model));
            Task highRisk = Task.Factory.StartNew(() => createTransactions(highrisk.Name, "high", model));

            // await all now
            taskList.AddRange(new List<Task>() { lowRisk, mediumRisk, highRisk });
            Task.WaitAll(taskList.ToArray());

            // now save your new stuff
            model.SaveChanges();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
        }
    }

    public static void createTransactions(string portfolioName, string risk, OoplesFinanceDBModel model)
    {
        try
        {
            IQueryable<StockRating> ratings = model.StockRatings.AsQueryable();

            switch (risk)
            {
                case "low":
                    **ratings = ratings.OrderByDescending(i => i.LongRating);**
                    break;
                case "medium":
                    ratings = ratings.OrderByDescending(i => i.MediumRating);
                    break;
                case "high":
                    ratings = ratings.OrderByDescending(i => i.ShortRating);
                    break;
                default:
                    ratings = ratings.OrderByDescending(i => i.MediumRating);
                    break;
            }

            // now add the top 10 stocks in each risk to each portfolio
            // start with low risk
            for (int k = 0; k < 10; k++)
            {
                StockRating rating = ratings.Where(j => j.MarginEnabled == true).Take(10).ElementAtOrDefault(k);
                Transactions transaction = new Transactions();
                transaction.Symbol = rating.Symbol;
                transaction.Market = rating.Market;
                transaction.PortfolioID = model.Portfolios.Where(i => i.Name == portfolioName).FirstOrDefault().ID;
                transaction.TransactionType = "Buy";
                transaction.CreatedOn = DateTime.Now;
                transaction.UpdatedOn = DateTime.Now;

                // finally set the quantity and price that we are buying based on the latest price
                switch (transaction.Market)
                {
                    case "amex":
                        transaction.Price = model.DailyAmexDatas.Where(i => i.Symbol == transaction.Symbol).OrderByDescending(j => j.Date).FirstOrDefault().AdjustedClose;
                        break;
                    case "nasdaq":
                        transaction.Price = model.DailyNasdaqDatas.Where(i => i.Symbol == transaction.Symbol).OrderByDescending(j => j.Date).FirstOrDefault().AdjustedClose;
                        break;
                    case "nyse":
                        transaction.Price = model.DailyNyseDatas.Where(i => i.Symbol == transaction.Symbol).OrderByDescending(j => j.Date).FirstOrDefault().AdjustedClose;
                        break;
                    default:
                        transaction.Price = model.DailyGlobalDatas.Where(i => i.Symbol == transaction.Symbol).OrderByDescending(j => j.Date).FirstOrDefault().AdjustedClose;
                        break;
                }

                // set the quanity that we are able to buy
                transaction.Quantity = Convert.ToInt32((model.Portfolios.Where(i => i.ID == transaction.PortfolioID).FirstOrDefault().StartingMargin / 10) / transaction.Price);
                model.Transactions.Add(transaction);
                Console.WriteLine(transaction.Symbol + " added to the" + portfolioName + " Portfolio");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
        }
    }

at System.Data.Entity.Internal.Linq.InternalQuery1.get_Expression() at System.Data.Entity.Internal.Linq.InternalSet1.get_Expression() at System.Data.Entity.Infrastructure.DbQuery1.System.Linq.IQueryable.get_Expression() at System.Linq.Queryable.OrderByDescending[TSource,TKey](IQueryable1 source, Expression`1 keySelector) at OoplesFinancePicker.Program.createTransactions(String portfolioName, String risk, OoplesFinanceDBModel model) in c:\Users\Franklin\Documents\Visual Studio 2013\Projects\OoplesFinancePicker\OoplesFinancePicker\Program.cs:line 99

DarthVegan
  • 1,501
  • 4
  • 23
  • 34
  • 2
    [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Soner Gönül Nov 28 '14 at 12:05
  • @SonerGönül There is no null values. I have inserted breakpoints and everything is fine. This code works just fine when I don't use threading so I know that the problem is related with the threading – DarthVegan Nov 28 '14 at 12:07
  • I guess you are passing the same model object to all the new Tasks. And the threads are overwriting the values? When you don't use threads it is synchronized. – Piyush Parashar Nov 28 '14 at 12:18
  • Also what @SonerGönül probably meant was that you can debug in case of Tasks, why the value is coming null. Maybe write to a textfile along with thread id. – Piyush Parashar Nov 28 '14 at 12:21
  • @PiyushParashar I am debugging and I have narrowed it down to that basic area but I believe it is because I'm passing model and still writing to it. I can't seem to come up with a better way to write the code – DarthVegan Nov 28 '14 at 12:25
  • Is it creation of transactions that is taking lot of time or actually running it? Sorry I am new to EF but I am assuming it will run only when you call SaveChanges(). Is that correct? – Piyush Parashar Nov 28 '14 at 12:29
  • @PiyushParashar It is the creation of the transactions but your comment gave me and idea that helped me fix it so be sure to create an answer and I will mark it as answered – DarthVegan Nov 28 '14 at 12:31

1 Answers1

1

I guess this is because the same model object is being accessed by all the threads and the values are getting overwritten. You need to synchronize the access to model object in the Tasks.

Also, think about what actually is taking more time. Is it the creation of transaction or actually saving changes to the database? Can you update the database once per transaction by one instead of adding all the transactions first and then doing one big update?

Piyush Parashar
  • 836
  • 8
  • 20