Асинхронность при рисовании в Windows FormsC#

Место общения программистов C#
Ответить
Anonymous
 Асинхронность при рисовании в Windows Forms

Сообщение Anonymous »

Мне нужно поэтапно нарисовать линейный список, параллельно отображая на каждом этапе сопроводительный текст, для этого я попробовал добавить либо ожидание с await Task.Delay(2000); или Thread.Sleep(2000).
Это происходит в непонятном порядке. Я попробовал нажать кнопку ожидания, в этом случае программа вылетает после первого ожидания при первом вызове отрисовки. Я видел в Интернете, что асинхронное рисование невозможно, но нет ли выхода?
Это мой код:

Код: Выделить всё

namespace DataStucturesVisualizer
{
public partial class Form1 : Form
{
private LinkedList linkedList = new LinkedList();
public Form1()
{
InitializeComponent();
listPanel.Paint += (s, e) => DrawLinkedListAsync(e.Graphics);
}

private async Task DrawNodeAsync(Graphics g, int x, int y, string value, bool isLastNode)
{
int width = 80;
int height = 50;
int splitHeight = height / 2;

g.DrawRectangle(Pens.Black, x, y, width, height);
AddCommandToFlowLayoutPanel("new(p)");
await Task.Delay(1000);

g.DrawLine(Pens.Black, x, y + splitHeight, x + width, y + splitHeight);
AddCommandToFlowLayoutPanel("read(f, p^.inf)");
await Task.Delay(1000);

g.DrawString(value, new Font("Arial", 10), Brushes.Black, x + 5, y + 5);
AddCommandToFlowLayoutPanel("read(f, p^.inf)");
await Task.Delay(1000);

if (isLastNode)
{
g.DrawString("nil", new Font("Arial", 10), Brushes.Black, x + 5, y + splitHeight + 5);
AddCommandToFlowLayoutPanel("p^.next := nil");
await Task.Delay(1000);
}
}
private void AddCommandToFlowLayoutPanel(string command)
{

Label commandLabel = new Label
{
Text = command,
AutoSize = true,
Font = new Font("Arial", 12),
ForeColor = Color.Black,
Padding = new Padding(5)
};

commandFlowLayoutPanel.Controls.Add(commandLabel);
}
private async Task DrawArrowAsync(Graphics g, int x1, int y1, int x2, int y2)
{

g.DrawLine(Pens.Black, x1, y1, x2, y2);
g.DrawLine(Pens.Black, x2, y2, x2 - 5, y2 - 5);
g.DrawLine(Pens.Black, x2, y2, x2 - 5, y2 + 5);

AddCommandToFlowLayoutPanel("p^.next := nil");
await Task.Delay(2000);
}

private async Task DrawLinkedListAsync(Graphics g)
{
int x = 10, y = 10;
const int nodeSpacing = 100;

int visibleXStart = -listPanel.AutoScrollPosition.X;
int visibleXEnd = visibleXStart + listPanel.Width;

var current = linkedList.First;
while (current != null)
{
string value = current.Value.ToString();
bool isLastNode = current.Next == null;

if (x + 80 >= visibleXStart &&  x 
{
tcs.SetResult(true);
button.Click -= handler;
};

button.Click += handler;

await tcs.Task;
}

private void UpdateVisualization()
{

int totalWidth = linkedList.Count * 100;
listPanel.AutoScrollMinSize = new Size(totalWidth, listPanel.Height);

listPanel.Refresh();
}

private async void listPanel_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;

g.TranslateTransform(listPanel.AutoScrollPosition.X, listPanel.AutoScrollPosition.Y);

await DrawLinkedListAsync(g);
}

private void addNode(object sender, EventArgs e)
{
if (int.TryParse(inputTextBox.Text, out int value))
{
linkedList.AddFirst(value);

UpdateVisualization();
}
}

private void removeNode(object sender, EventArgs e)
{
if (linkedList.Count > 0)
{
linkedList.RemoveFirst();
UpdateVisualization();
}
}
}

}
Основная задача - просмотреть процесс создания списка шаг за шагом: создать указатель, записать в него данные, создать указатель на следующий элемент. Поэтому я пытаюсь показать это с помощью асинхронных задач

Код: Выделить всё

private static async Task WaitForButtonClick(Button b)
{
// Создаем новый экземпляр TaskCompletionSource для ожидания нажатия кнопки
TaskCompletionSource buttonClickedTaskCompletionSource = new TaskCompletionSource();

// Подписываемся на событие Click кнопки
EventHandler buttonClickEventHandler = null;
buttonClickEventHandler = (s, e) =>
{
// Устанавливаем результат задачи как true, когда кнопка была нажата
buttonClickedTaskCompletionSource.SetResult(true);

// Отписываемся от события, чтобы избежать утечки памяти
b.Click -= buttonClickEventHandler;
};
b.Click += buttonClickEventHandler;

// Ожидаем завершения задачи
return await buttonClickedTaskCompletionSource.Task;

}
или Thread.sleep
или другие способы, которые вы можете порекомендовать.

Подробнее здесь: https://stackoverflow.com/questions/792 ... dows-forms
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»