2015-01-26 45 views
0

我正在尝试生成地图。我创建了一个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新手。

+0

异步调用的操作上的调度员,而不是同步您的循环可转化为并行.ForEach循环 – Sievajet 2015-01-26 23:07:33

+0

您使用的是哪个版本的.Net? – i3arnon 2015-01-26 23:11:04

+0

我知道每个人都可以使用并行,但我需要使用任务来完成。 .Net 4,5 – Safiron 2015-01-26 23:40:56

回答

1

您正在通过调用Task.Wait来阻止UI线程,其中您在UI线程上调用Dispatcher.Invoke的某些内容。这些任务等待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

+0

它可以工作,但整个过程要比非并行解决方案长。我猜它对吗? 此外,当我调用GenerateMapParallel(..)方法时,我得到警告“该呼叫没有等待......并且我应该使用异步”我该怎么做?“ – Safiron 2015-01-26 23:42:04

+0

@Safiron很可能。真正的并行任何事情,因为调度员使用一个单一的线程,其余的可以忽略不计。 – i3arnon 2015-01-26 23:44:09

+0

有用的,谢谢 – Safiron 2015-01-26 23:47:25