Я использую библиотеку .NET Chart Control, поставляемую с .NET 4.0 Beta 2, для создания и сохранения изображений на диск в фоновом потоке. Однако я не показываю диаграмму на экране, просто создаю диаграмму, сохраняю ее на диск и уничтожаю. Примерно так:
public void GeneratePlot(IList<DataPoint> series, Stream outputStream) {
using (var ch = new Chart()) {
ch.ChartAreas.Add(new ChartArea());
var s = new Series();
foreach (var pnt in series) s.Points.Add(pnt);
ch.Series.Add(s);
ch.SaveImage(outputStream, ChartImageFormat.Png);
}
}
Создание и сохранение каждого графика занимало около 300 - 400 мс. У меня есть потенциально сотни диаграмм для создания, поэтому я решил использовать Parallel.For()
для распараллеливания этих задач. У меня есть 8-ядерный компьютер, однако, когда я пытаюсь создать 4 графика одновременно, время создания / сохранения моего графика увеличивается до 800 - 1400 мс, почти все из которых потребляются Chart.SaveImage
.
Я подумал, что это может быть ограничение дискового ввода-вывода, поэтому для проверки я изменил последнюю строку на:
ch.SaveImage(Stream.Null, ChartImageFormat.Png);
Даже при записи в нулевой поток производительность остается примерно такой же (800 - 1400 мс).
Разве я не должен создавать изображения в фоновых потоках параллельно с этой библиотекой или я что-то не так делаю?
Спасибо
РЕДАКТИРОВАТЬ: Добавлен полный пример кода
Просто измените флаг, переданный на CreateCharts()
, чтобы проверить параллельный или последовательный.
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms.DataVisualization.Charting;
namespace ConsoleChartTest
{
class Program
{
public static void GeneratePlot(IEnumerable<DataPoint> series, Stream outputStream)
{
long beginTime = Environment.TickCount;
using (var ch = new Chart())
{
ch.ChartAreas.Add(new ChartArea());
var s = new Series();
foreach (var pnt in series)
s.Points.Add(pnt);
ch.Series.Add(s);
long endTime = Environment.TickCount;
long createTime = endTime - beginTime;
beginTime = Environment.TickCount;
ch.SaveImage(outputStream, ChartImageFormat.Png);
endTime = Environment.TickCount;
long saveTime = endTime - beginTime;
Console.WriteLine("Thread Id: {0,2} Create Time: {1,3} Save Time: {2,3}",
Thread.CurrentThread.ManagedThreadId, createTime, saveTime);
}
}
public static void CreateCharts(bool parallel)
{
var data = new DataPoint[20000];
for (int i = 0; i < data.Length; i++)
{
data[i] = new DataPoint(i, i);
}
if (parallel)
{
Parallel.For(0, 10, (i) => GeneratePlot(data, Stream.Null));
}
else
{
for (int i = 0; i < 10; i++)
GeneratePlot(data, Stream.Null);
}
}
static void Main(string[] args)
{
Console.WriteLine("Main Thread Id: {0,2}", Thread.CurrentThread.ManagedThreadId);
long beginTime = Environment.TickCount;
CreateCharts(false);
long endTime = Environment.TickCount;
Console.WriteLine("Total Time: {0}", endTime - beginTime);
}
}
}