对象引用未设置为线程任务内对象的实例

时间:2014-11-28 12:03:23

标签: c# multithreading linq entity-framework

我正在使用线程化任务来帮助加速我的程序的一部分非常慢但我得到了上面的例外,我似乎无法找到我正在处理错误的线程导致出现此错误。我收到的错误就是我在下面加粗的那一行。我也粘贴了我的完整堆栈跟踪。

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.InternalQuery 1.get_Expression() at System.Data.Entity.Internal.Linq.InternalSet 1.get_Expression()    在System.Data.Entity.Infrastructure.DbQuery 1.System.Linq.IQueryable.get_Expression() at System.Linq.Queryable.OrderByDescending[TSource,TKey](IQueryable 1源,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:第99行

1 个答案:

答案 0 :(得分:1)

我想这是因为所有线程都在访问相同的模型对象,并且值被覆盖。您需要在“任务”中同步对模型对象的访问权限。

另外,想想实际上花费更多时间的是什么。是创建事务还是实际保存对数据库的更改?您是否可以按事务更新数据库一次,而不是先添加所有事务然后再进行一次大更新?