从多个任务访问 Canvas
Accessing Canvas from Multiple Tasks
我正在尝试生成地图。我创建了一个 2D 布尔数组,它代表地图的可访问和不可访问部分。现在我正在尝试通过多个任务在 canvas 中绘制一些矩形。我不知道我做错了什么。
private void GenerateMapParallel(Canvas cMap)
{
cMap.Children.Clear();
var task1 = Task.Factory.StartNew(() => Generate(0, 330, cMap));
var task2 = Task.Factory.StartNew(() => Generate(331, 660, cMap));
Task.WaitAll(task1, task2);
}
private void Generate(int start, int stop, Canvas cMap)
{
for (int i = start; i < stop; i++)
{
for (int j = 0; j < Map.instance.height; j++)
{
if (Map.instance.map[i, j] == false)
{
if(cMap.Dispatcher.CheckAccess())
{
cMap.Children.Add(new Rectangle() { Width = 1, Height = 1, Margin = new Thickness(i, j, 0, 0), Fill = Brushes.Gray });
}
else
{
cMap.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => { cMap.Children.Add(new Rectangle() { Width = 1, Height = 1, Margin = new Thickness(i, j, 0, 0), Fill = Brushes.Gray }); }));
}
}
}
}
}
应用程序无法加载,就像它在某个地方处于无限循环中一样。 Task1 生成上半部分,Task2 生成下半部分。任何想法如何更好地做到这一点?我是TPL的新人。
您在使用 Dispatcher.Invoke
在 UI 线程上调用某些内容的任务上调用 Task.Wait
阻塞了 UI 线程。任务等待 UI 线程空闲,而 UI 线程等待任务完成。这会导致死锁。
你应该异步等待 await
:
private async Task GenerateMapParallel(Canvas cMap)
{
cMap.Children.Clear();
var task1 = Task.Factory.StartNew(() => Generate(0, 330, cMap));
var task2 = Task.Factory.StartNew(() => Generate(331, 660, cMap));
await Task.WhenAll(task1, task2);
}
打破僵局的另一种方法是在调度程序上异步调用操作,而不是与 Dispatcher.BeginInvoke
同步调用
我正在尝试生成地图。我创建了一个 2D 布尔数组,它代表地图的可访问和不可访问部分。现在我正在尝试通过多个任务在 canvas 中绘制一些矩形。我不知道我做错了什么。
private void GenerateMapParallel(Canvas cMap)
{
cMap.Children.Clear();
var task1 = Task.Factory.StartNew(() => Generate(0, 330, cMap));
var task2 = Task.Factory.StartNew(() => Generate(331, 660, cMap));
Task.WaitAll(task1, task2);
}
private void Generate(int start, int stop, Canvas cMap)
{
for (int i = start; i < stop; i++)
{
for (int j = 0; j < Map.instance.height; j++)
{
if (Map.instance.map[i, j] == false)
{
if(cMap.Dispatcher.CheckAccess())
{
cMap.Children.Add(new Rectangle() { Width = 1, Height = 1, Margin = new Thickness(i, j, 0, 0), Fill = Brushes.Gray });
}
else
{
cMap.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => { cMap.Children.Add(new Rectangle() { Width = 1, Height = 1, Margin = new Thickness(i, j, 0, 0), Fill = Brushes.Gray }); }));
}
}
}
}
}
应用程序无法加载,就像它在某个地方处于无限循环中一样。 Task1 生成上半部分,Task2 生成下半部分。任何想法如何更好地做到这一点?我是TPL的新人。
您在使用 Dispatcher.Invoke
在 UI 线程上调用某些内容的任务上调用 Task.Wait
阻塞了 UI 线程。任务等待 UI 线程空闲,而 UI 线程等待任务完成。这会导致死锁。
你应该异步等待 await
:
private async Task GenerateMapParallel(Canvas cMap)
{
cMap.Children.Clear();
var task1 = Task.Factory.StartNew(() => Generate(0, 330, cMap));
var task2 = Task.Factory.StartNew(() => Generate(331, 660, cMap));
await Task.WhenAll(task1, task2);
}
打破僵局的另一种方法是在调度程序上异步调用操作,而不是与 Dispatcher.BeginInvoke