這是我第一次工作woth一個並行for循環,我理解的基本知識,你可以看到我的代碼如下,但我不理解如何使內部變量循環線程安全。使用線程安全變量與並行for循環C#
目前,我不斷得到錯誤爲:序列包含在我的計算類中沒有的元素時,它正在執行對數據的計算。我是否缺少一些簡單的東西來使所有線程安全?
更新:我添加了Calculations類的所有相關代碼,其中顯示了一個方法作爲返回常量的示例。Sequence沒有包含任何元素異常,並且目前爲止我嘗試修復此問題(異常仍在進行中)
更新2:我在我的代碼中添加了自定義類,它應該允許它現在編譯。
public static async Task Test()
{
Vector<double> vectorArrayBuy = null;
Vector<double> vectorArraySell = null;
Calculations calcTemp = null;
try
{
using (financeEntities context = new financeEntities())
{
List<string> symbolList = new List<string>();
symbolList = GetStockSymbols("nasdaq");
foreach (string symbol in symbolList)
{
var query = await context.DailyStockDatas.Where(i => i.Symbol == symbol && i.Market == "nasdaq").ToListAsync();
if (query.Count >= 200)
{
List<MultipleRegressionInfo> listMRInfo = new List<MultipleRegressionInfo>();
Calculations calc = new Calculations(query, j);
calcTemp = calc;
Parallel.For(0, 200, j =>
{
var targetValueBuy = calc.ListCalculationData.Select(i => i.MRTargetValueBuy).ToList();
var targetValueSell = calc.ListCalculationData.Select(i => i.MRTargetValueSell).ToList();
vectorArrayBuy = CreateVector.Dense(targetValueBuy.ToArray());
vectorArraySell = CreateVector.Dense(targetValueSell.ToArray());
var name = calc.ListCalculationData.First();
IEnumerable<double> value;
value = calc.ListCalculationData.Select(i => i.WilliamsR);
MultipleRegressionInfo r1 = Rn(value, vectorArrayBuy, nameof(name.WilliamsR), j, calc);
listMRInfo.Add(r1);
});
class Calculations
{
public List<DailyStockData> Data { get; set; }
public ConcurrentBag<CalculationData> ListCalculationData { get; set; }
public Calculations(List<DailyStockData> dailyData, int days)
{
lock (thisLock)
{
Data = dailyData;
// initiate the data
ListCalculationData = new ConcurrentBag<CalculationData>();
for (int i = 0; i < Data.Count; i++)
{
var currentDate = Data.ElementAt(i).Date;
CalculationData calc = new CalculationData(currentCalcData);
calc.WilliamsR = CalculateWilliamsR(days, currentDate);
// add current calculator class to the list
ListCalculationData.Add(calc);
}
}
}
public double CalculateWilliamsR(int days, DateTime startingDate)
{
double williamsR = 0;
double highestHigh = 0;
double currentClose = 0;
double lowestLow = 0;
try
{
highestHigh = FindMaxOrMin(days, startingDate, MaxOrMinType.HighestHigh);
lowestLow = FindMaxOrMin(days, startingDate, MaxOrMinType.LowestLow);
currentClose = (double)Data.Where(i => i.Date <= startingDate).Last().Close;
williamsR = -100 * ((highestHigh - currentClose)/(highestHigh - lowestLow));
}
catch (Exception ex)
{
williamsR = 0;
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
return williamsR;
}
public enum MaxOrMinType
{
HighestHigh,
LowestLow,
HighestClose,
LowestClose
}
public double FindMaxOrMin(int days, DateTime startingDate, MaxOrMinType type)
{
double maxMin = 0;
try
{
lock (thisLock)
{
switch (type)
{
// gets Sequence contains no elements exceptions at all of the below lines
case MaxOrMinType.HighestClose:
maxMin = (double)Data.Where(i => i.Date <= startingDate).Take(days).Max(i => i.Close);
break;
case MaxOrMinType.HighestHigh:
maxMin = (double)Data.Where(i => i.Date <= startingDate).Take(days).Max(i => i.High);
break;
case MaxOrMinType.LowestClose:
maxMin = (double)Data.Where(i => i.Date <= startingDate).Take(days).Min(i => i.Close);
break;
case MaxOrMinType.LowestLow:
maxMin = (double)Data.Where(i => i.Date <= startingDate).Take(days).Min(i => i.Low);
break;
default:
break;
}
}
}
catch (Exception ex)
{
maxMin = 0;
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
return maxMin;
}
public class DailyStockData
{
public DailyStockData();
public int ID { get; set; }
public string Symbol { get; set; }
public string Market { get; set; }
public DateTime Date { get; set; }
public decimal Open { get; set; }
public decimal High { get; set; }
public decimal Low { get; set; }
public decimal Close { get; set; }
public decimal AdjustedClose { get; set; }
public long Volume { get; set; }
}
public class CalculationData
{
public CalculationData(CalculationData calcData)
{
Date = calcData.Date;
Open = calcData.Open;
High = calcData.High;
Low = calcData.Low;
Close = calcData.Close;
AdjustedClose = calcData.AdjustedClose;
Volume = calcData.Volume;
WilliamsR = calcData.WilliamsR;
}
public CalculationData() { }
public DateTime Date { get; set; }
public double Open { get; set; }
public double High { get; set; }
public double Low { get; set; }
public double Close { get; set; }
public double AdjustedClose { get; set; }
public double Volume { get; set; }
public double WilliamsR { get; set; }
}
評論不適用於擴展討論;這個對話已經[轉移到聊天](http://chat.stackoverflow.com/rooms/157820/discussion-on-question-by-user-3610374-using-a-thread-safe-variable-with-a-parall) 。 – Andy