从多个任务访问画布

时间:2015-01-26 23:02:03

标签: c# .net wpf canvas task-parallel-library

我正在尝试生成地图。我创建了一个2D布尔数组,它表示地图的可访问和不可访问的部分。现在我试图通过多个任务在画布中绘制一些矩形。我不知道我做错了什么。

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的新人。

1 个答案:

答案 0 :(得分:1)

您正在使用Task.Wait在UI线程上调用某些内容的任务上调用Dispatcher.Invoke来阻止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同步调用