Мне нужно поэтапно нарисовать линейный список, параллельно отображая на каждом этапе сопроводительный текст, для этого я попробовал добавить либо ожидание с 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
или другие способы, которые вы можете порекомендовать.
Мне нужно поэтапно нарисовать линейный список, параллельно отображая на каждом этапе сопроводительный текст, для этого я попробовал добавить либо ожидание с await Task.Delay(2000); или Thread.Sleep(2000). Это происходит в непонятном порядке. Я попробовал нажать кнопку ожидания, в этом случае программа вылетает после первого ожидания при первом вызове отрисовки. Я видел в Интернете, что асинхронное рисование невозможно, но нет ли выхода? Это мой код: [code]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) {
} [/code] Основная задача - просмотреть процесс создания списка шаг за шагом: создать указатель, записать в него данные, создать указатель на следующий элемент. Поэтому я пытаюсь показать это с помощью асинхронных задач [code]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;
} [/code] или Thread.sleep или другие способы, которые вы можете порекомендовать.