В моем приложении Winforms я пытаюсь воссоздать метод Монте-Карло для приближения PI.Сама форма состоит из поля, в котором пользователь указывает количество точек, и панели, на которой я хочу нарисовать.Однако для этого примера предположим, что сумма будет постоянной.
private int Amount = 10000;
private int InCircle = 0, Points = 0;
private Pen myPen = new Pen(Color.White);
private void DrawingPanel_Paint(object sender, PaintEventArgs e)
{
int w = DrawingPanel.Width, h = DrawingPanel.Height;
e.Graphics.TranslateTransform(w / 2, h / 2);
//drawing the square and circle in which I will display the points
var rect = new Rectangle(-w / 2, -h / 2, w - 1, h - 5);
e.Graphics.DrawRectangle(myPen, rect);
e.Graphics.DrawEllipse(myPen, rect);
double PIE;
int X, Y;
var random = new Random();
for (int i = 0; i < Amount; i++)
{
X = random.Next(-(w / 2), (w / 2) + 1);
Y = random.Next(-(h / 2), (h / 2) + 1);
Points++;
if ((X * X) + (Y * Y) < (w / 2 * h / 2))
{
InCircle++;
e.Graphics.FillRectangle(Brushes.LimeGreen, X, Y, 1, 1);
}
else
{
e.Graphics.FillRectangle(Brushes.Cyan, X, Y, 1, 1);
}
//just so that the points appear with a tiny delay
Thread.Sleep(1);
}
PIE = 4 * ((double)InCircle/(double)Points);
}
И это работает.Визуализация отличная.Однако теперь я хотел бы воссоздать это асинхронно, чтобы приложение отображалось в фоновом режиме, а приложение по-прежнему отвечало за него, а пользователь мог сделать что-то еще или даже просто переместить окно.Первоначально я сделал второй метод, который выполняет рисование, которое я вызываю из обработчика событий:
private double Calculate(PaintEventArgs e)
{
int w = DrawingPanel.Width, h = DrawingPanel.Height;
double PIE;
int X, Y;
var random = new Random();
for (int i = 0; i < Amount; i++)
{
X = random.Next(-(w / 2), (w / 2) + 1);
Y = random.Next(-(h / 2), (h / 2) + 1);
Points++;
if ((X * X) + (Y * Y) < (w / 2 * h / 2))
{
InCircle++;
e.Graphics.FillRectangle(Brushes.LimeGreen, X, Y, 1, 1);
}
else
{
e.Graphics.FillRectangle(Brushes.Cyan, X, Y, 1, 1);
}
Thread.Sleep(1);
}
PIE = 4 * ((double)InCircle/(double)Points);
return PIE;
}
private void DrawingPanel_Paint(object sender, PaintEventArgs e)
{
int w = DrawingPanel.Width, h = DrawingPanel.Height;
e.Graphics.TranslateTransform(w / 2, h / 2);
var rect = new Rectangle(-w / 2, -h / 2, w - 1, h - 5);
e.Graphics.DrawRectangle(myPen, rect);
e.Graphics.DrawEllipse(myPen, rect);
var result = Calculate(e);
}
И это тоже хорошо работало.Пока я не сделал обработчик событий асинхронным.
private async void DrawingPanel_Paint(object sender, PaintEventArgs e) {...}
Теперь, когда я пытаюсь запустить метод Calculate через Task.Run или когда я изменяю его тип возвращаемого значения на Task и запускаю его, я получаю ошибку: «Параметр недействителен» в следующей строке:
e.Graphics.FillRectangle(Brushes.LimeGreen, X, Y, 1, 1);
Теперь вопрос, возможно ли рисовать на панели асинхронно, чтобы другие части приложения не были заблокированы?И если нет, есть ли способ воссоздать этот алгоритм, используя любой другой способ (не обязательно панель)?Приветствия.