2013-07-16 3 views
0

Я оклейки 4 фрагменты кода, где распараллеливания будет предпринята попытка использовать следующие интерфейсы:синхронизации Thread с помощью задач и параллельных интерфейсов API

Parallel.ForEach 
Parallel.Invoke 
Task.Run 
Task.Factory.StartNew 

Проблема пытается распараллелить такие, что Есть два для петель, внутренних и внешних, так и для каждое выполнение внешнего цикла во внутреннем цикле должно выполняться в Parallel.

Я могу заставить его работать с использованием Parallel.ForEach, а все остальные приводят к исключению, как для внутреннего счетчика, это значение превышает индекс массива, когда, на мой взгляд, этого не должно быть. Также индекс пропускает цель на одно более высокое значение, например, когда размер индекса равен 500, он пытается получить доступ к значению 500, когда в идеале он должен остановиться на 499. Я что-то упускаю. Ниже приведены фрагменты кода, пожалуйста смотрите:

Parallel.ForEach (рабочий)

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Threading.Tasks; 

namespace TestThreads 
{  
    class Elements 
    { 
     public int innerValue; 
     public int outerValue; 

     public Elements(int innerValue, int outerValue) 
     { 
      this.innerValue = innerValue; 
      this.outerValue = outerValue; 
     } 
    } 

    class Program 
    { 
     private static int threadingCounter = 0; 
     private static int innerCounter = 500; 
     private static int outerCounter = 1000; 
     private static int[,] inOut; 
     private static int hitCount = 0; 
     private static int exceptionCount = 0; 
     private static List<int> innerCount = new List<int>(); 



     static void Main(string[] args) 
     { 
      inOut = new int[innerCounter, outerCounter]; 
      Program myProgram = new Program(); 

      for (int iCount = 0; iCount < innerCounter; iCount++) 
       innerCount.Add(iCount); 

      try 
      { 
       for (int outer = 0; outer < outerCounter; outer++) 
       { 
        Parallel.ForEach<int>(innerCount, inner => 
        { 
         myProgram.ThreadCall(new Elements(inner,outer)); 
        } 
        ); 

        Console.WriteLine("Main Thread Released Post Wait ..."); 
        Console.WriteLine("Hit Count :: " + hitCount); 
        Console.WriteLine("Exception Count :: " + exceptionCount); 

        if (threadingCounter != 0) 
         Console.WriteLine("Threading Counter post Inner Loop :: " + threadingCounter); 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Exception :: " + ex.Message); 
      } 
      finally 
      {     
       if (innerCount != null) 
        innerCount = null; 

      } 
     } 


     public void ThreadCall(object state) 
     { 
      try 
      { 
       Interlocked.Increment(ref hitCount); 

       Elements localElement = (Elements)state; 
       int localInner = localElement.innerValue; 
       int localOuter = localElement.outerValue; 
       int finalValue = inOut[localInner, localOuter]; 
      } 
      catch (Exception ex) 
      {    
       Console.WriteLine("Exception :: " + ex.Message); 
      } 
     } 
    } 
} 

Parallel.Invoke (Failing с массивом из значения индекса, пытается извлечь внутренний индекс - 500)

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Threading.Tasks; 

namespace TestThreads 
{ 
    /// <summary> 
    /// 
    /// </summary> 
    class Elements 
    { 
     public int innerValue; 
     public int outerValue; 

     public Elements(int innerValue, int outerValue) 
     { 
      this.innerValue = innerValue; 
      this.outerValue = outerValue; 
     } 
    } 

    /// <summary> 
    /// 
    /// </summary> 
    class Program 
    { 
     private static int innerCounter = 500; 
     private static int outerCounter = 1000; 
     private static int[,] inOut; 
     private static int hitCount = 0; 
     private static int exceptionCount = 0; 

     private static List<Action> alSync = new List<Action>(); 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="args"></param> 
     static void Main(string[] args) 
     { 
      inOut = new int[innerCounter, outerCounter]; 
      Program myProgram = new Program(); 

      try 
      { 
       for (int outer = 0; outer < outerCounter; outer++) 
       { 

        for (int inner = 0; inner < innerCounter; inner++) 
         alSync.Add(() => myProgram.ThreadCall(new Elements(inner, outer))); 

        Parallel.Invoke(alSync.ToArray());        
        alSync.Clear(); 

        Console.WriteLine("Main Thread Released Post Wait ..."); 
        Console.WriteLine("Hit Count :: " + hitCount); 
        Console.WriteLine("Exception Count :: " + exceptionCount); 
       } 

      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Exception :: " + ex.Message); 
      } 
      finally 
      { 
       if (alSync != null) 
        alSync = null; 
      } 
     } 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="state"></param> 
     public void ThreadCall(object state) 
     { 
      try 
      { 
       Interlocked.Increment(ref hitCount); 
       Elements localElement = (Elements)state; 
       int localInner = localElement.innerValue; 
       int localOuter = localElement.outerValue; 
       int finalValue = inOut[localInner, localOuter]; 
      } 
      catch (Exception ex) 
      { 
       Interlocked.Increment(ref exceptionCount); 
       Console.WriteLine("Exception :: " + ex.Message); 
      } 

     } 
    } 
} 

Task.Run (в противном случае с массивом из значения индекса, пытается извлечь внутренний индекс - 500)

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Threading.Tasks; 

namespace TestThreads 
{ 
    /// <summary> 
    /// 
    /// </summary> 
    class Elements 
    { 
     public int innerValue; 
     public int outerValue; 

     public Elements(int innerValue, int outerValue) 
     { 
      this.innerValue = innerValue; 
      this.outerValue = outerValue; 
     } 
    } 

    /// <summary> 
    /// 
    /// </summary> 
    class Program 
    { 
     private static int innerCounter = 500; 
     private static int outerCounter = 1000; 
     private static int[,] inOut; 
     private static int hitCount = 0; 
     private static int exceptionCount = 0; 

     private static List<Task> tlSync = new List<Task>(); 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="args"></param> 
     static void Main(string[] args) 
     { 
      inOut = new int[innerCounter, outerCounter]; 
      Program myProgram = new Program(); 

      try 
      { 
       for (int outer = 0; outer < outerCounter; outer++) 
       {     

        for (int inner = 0; inner < innerCounter; inner++) 
         tlSync.Add(Task.Run(() => myProgram.ThreadCall(new Elements(inner, outer)))); 

        Task.WaitAll(tlSync.ToArray()); 
        tlSync.Clear(); 

        Console.WriteLine("Main Thread Released Post Wait ..."); 
        Console.WriteLine("Hit Count :: " + hitCount); 
        Console.WriteLine("Exception Count :: " + exceptionCount); 
       } 

      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Exception :: " + ex.Message); 
      } 
      finally 
      {    
       if (tlSync != null) 
        tlSync = null; 
      } 
     } 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="state"></param> 
     public void ThreadCall(object state) 
     { 
      try 
      { 
       Interlocked.Increment(ref hitCount); 
       Elements localElement = (Elements)state; 
       int localInner = localElement.innerValue; 
       int localOuter = localElement.outerValue; 
       int finalValue = inOut[localInner, localOuter]; 
      } 
      catch (Exception ex) 
      { 
       Interlocked.Increment(ref exceptionCount); 
       Console.WriteLine("Exception :: " + ex.Message); 
      }   

     } 
    } 
} 

Task.Factory.StartNew (В противном случае с массивом из значения индекса, пытается извлечь внутренний индекс - 500)

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Threading.Tasks; 

namespace TestThreads 
{ 
    /// <summary> 
    /// 
    /// </summary> 
    class Elements 
    { 
     public int innerValue; 
     public int outerValue; 

     public Elements(int innerValue, int outerValue) 
     { 
      this.innerValue = innerValue; 
      this.outerValue = outerValue; 
     } 
    } 

    /// <summary> 
    /// 
    /// </summary> 
    class Program 
    { 
     private static int innerCounter = 500; 
     private static int outerCounter = 1000; 
     private static int[,] inOut; 
     private static int hitCount = 0; 
     private static int exceptionCount = 0; 

     private static List<Task> tlSync = new List<Task>(); 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="args"></param> 
     static void Main(string[] args) 
     { 
      inOut = new int[innerCounter, outerCounter]; 
      Program myProgram = new Program(); 

      try 
      { 
       for (int outer = 0; outer < outerCounter; outer++) 
       { 

        for (int inner = 0; inner < innerCounter; inner++) 
         tlSync.Add(Task.Factory.StartNew(() => 
myProgram.ThreadCall(new Elements(inner, outer)))); 

        Task.WaitAll(tlSync.ToArray()); 
        tlSync.Clear(); 

        Console.WriteLine("Main Thread Released Post Wait ..."); 
        Console.WriteLine("Hit Count :: " + hitCount); 
        Console.WriteLine("Exception Count :: " + exceptionCount); 
       } 

      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Exception :: " + ex.Message); 
      } 
      finally 
      { 
       if (tlSync != null) 
        tlSync = null; 
      } 
     } 

     /// <summary> 
     /// 
     /// </summary> 
     /// <param name="state"></param> 
     public void ThreadCall(object state) 
     { 
      try 
      { 
       Interlocked.Increment(ref hitCount); 
       Elements localElement = (Elements)state; 
       int localInner = localElement.innerValue; 
       int localOuter = localElement.outerValue; 
       int finalValue = inOut[localInner, localOuter]; 
      } 
      catch (Exception ex) 
      { 
       Interlocked.Increment(ref exceptionCount); 
       Console.WriteLine("Exception :: " + ex.Message); 
      } 

     } 
    } 
} 
+0

Будет использование tlSync? и что делает ThreadCall? – Robert

ответ

0

Не уверен, что использование tlSync это я не посмотрите, почему вы хотели бы перенаправить задачи в общий список.

Если вы хотите сделать некоторые вещи и обновить пользовательский интерфейс вы можете, возможно, вдохновит от этой функции я использовал для программы форм я когда-то писал

var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
someList 
    .ForEach(f => Task.Factory.StartNew(() => 
    { 
     // do stuff 
    }) 
    .ContinueWith(task => 
    { 
     if (task.IsCompleted) 
     { 
      // update UI 
      // called after each task above completes 
     } 
    }, ui)); 

Или вы могли бы иметь проблему замыкания с внутренним/внешним, и вы можете попробовать изменить этот код

for (int inner = 0; inner < innerCounter; inner++) 
    tlSync.Add(Task.Factory.StartNew(() => myProgram.ThreadCall(new Elements(inner, outer)))); 

Для этого

for (int inner = 0; inner < innerCounter; inner++) { 
    var nInner = inner; 
    var nOuter = outer; 
    tlSync.Add(Task.Factory.StartNew(() => myProgram.ThreadCall(new Elements(nInner, nOuter))));  
} 
+0

Задачи переносятся в общий список, так что после каждого параллельного выполнения внутреннего цикла для каждого значения цикла Outer один и тот же список может быть передан в API WaitAll задачи как массив, ожидающий завершения всех задач, перед выполнением следующей последовательности цикла Outer. Я не ищу того, что вы предложили. Мой код - это код запуска, пожалуйста, предложите любые изменения, которые вы можете рассмотреть. –

+0

Вы пытались переместить '' Task.WaitAll (tlSync.ToArray()); '' из циклов. Не понимаю, зачем это нужно в цикле. – Robert

+0

Если это не поможет попробовать googling: C# task closures – Robert

Смежные вопросы