private static void EvaluateFormula(FormulaTree formulaTree, Range[] ranges, Size areaSize, int threadsCount, float[] evaluatedValuesBuffer) { Stopwatch evaluationStopwatch = new Stopwatch(); evaluationStopwatch.Start(); if (evaluatedValuesBuffer.Length != areaSize.Square) throw new ArgumentException("Result buffer size isn't equal to ranges area size.", "evaluatedValuesBuffer"); int xCount = areaSize.Width; int yCount = areaSize.Height; if (threadsCount < 1) threadsCount = 1; ranges = ranges.Select((r, i) => new Range(r.Start, r.End, i % 2 == 0 ? areaSize.Width : areaSize.Height)).ToArray(); const int progressSteps = 100; using (ProgressReporter.CreateScope(progressSteps)) { int steps = 0; double lastProgress = 0; double progress = 0; ProgressObserver progressObserver = new ProgressObserver(p => progress = p.Progress); Task[] tasks = new Task[threadsCount]; int yStepCount = yCount/threadsCount; for (int i = 0; i < threadsCount; i++) { int li = i; tasks[i] = Task.Run(() => { FormulaTree ft = li == 0 ? formulaTree : FormulaTreeSerializer.Deserialize(FormulaTreeSerializer.Serialize(formulaTree)); int yStart = li * yStepCount; ProgressReporter.Subscribe(progressObserver); ft.EvaluateRangesIn2DProjection(ranges, xCount, yStart, yStepCount, evaluatedValuesBuffer); }); } while (tasks.Any(t => t.Status != TaskStatus.RanToCompletion && t.Status != TaskStatus.Faulted && t.Status != TaskStatus.Canceled)) { Task.WaitAny(tasks, 100); double progressCopy = progress; int inc = (int)((progressCopy - lastProgress) * progressSteps); if (inc > 0) { for (int i = 0; i < inc && steps < progressSteps; i++) { ProgressReporter.Increase(); steps++; } lastProgress = progress; } } Task.WaitAll(); } //double x = 1; //double y = 2; //double z = 3; //double w = 4; //double x1 = -1; //double y1 = -2; //double z1 = -3; //double w1 = -4; //Stopwatch stopwatch2 = new Stopwatch(); //stopwatch2.Start(); //double[] arr = new double[Ranges[0].Count*Ranges[1].Count]; //for (int i = 0; i < arr.Length; i++) //{ // arr[i] = Math.Sqrt((Math.Sin(x) * Math.Sin(y) + Math.Sin(z) * Math.Sin(w)) * (Math.Sin(x1) * Math.Sin(y1) + Math.Sin(z1) * Math.Sin(w1))); // x += 0.1; // y += 0.1; // z += 0.1; // w += 0.1; // x1 += 0.3; // y1 += 0.3; // z1 += 0.3; // w1 += 0.3; //} //stopwatch2.Stop(); evaluationStopwatch.Stop(); }
public static string ToString(Range[] ranges) { IEnumerable<string> rangeStrings = ranges.Select(r => r.ToString(true)); return string.Join(";", rangeStrings.ToArray()); }