2016-12-31 6 views
3

У меня есть проблема с parllel Задачи Мой кодПараллельные задачи Вызов статической функции

namespace ITDevices 
{ 
    using System.Linq; 
    using System.Collections.Generic; 
    using System.Threading.Tasks; 
    using System; 

    /*Device Modal*/ 
    public class Device 
    { 
     public string IP { get; set; } 
     public string Name { get; set; } 
     public string MAC { get; set; } 
    } 

    /*Entry Class*/ 
    class Program 
    { 
     static async void Main(string[] args) 
     { 
      List<Task<Device>> Tasks = new List<Task<Device>>(); 

      for(int i=2;i==0;i--) 
      { 
       Tasks.Add(Task.Factory.StartNew<Device>(
        ()=> { 
          Device free = Helper.GetFreeDevice(); 
          return free; 
         } 
        ));  
      } 
      await Task.WhenAll(Tasks.ToArray()); 
      foreach(Task<Device> item in Tasks) 
      { 
       Console.WriteLine(item.Result.IP); 
      } 
      Console.ReadLine(); 
     } 
    } 
    /*Devices Helper*/ 
    static class Helper 
    { 


     public static List<Device> UsedDevices = new List<Device>(); 

     public static Device GetFreeDevice() 
     { 
      List<Device> OnlineDevices = new List<Device>() 
      { 
       new Device { IP="192.168.1.15",Name="PerryLabtop",MAC="AC:DS:F2:CC:2D:7A"}, 
       new Device { IP="192.168.1.20",Name="MAYA-PC",MAC="7D:E9:2C:FF:E7:2D"}, 
       new Device { IP="192.168.1.2",Name="server",MAC="D8:C2:A4:DC:E5:3A"} 
      }; 

      Device FreeDevice = OnlineDevices.Where(x => !UsedDevices.Contains(x)).SingleOrDefault(); 
      if (FreeDevice != null) 
       UsedDevices.Add(FreeDevice); 
      return FreeDevice; 
     } 
    } 
} 

//Output 
//192.168.1.15 
//192.168.1.15 

But expected output must be 
//192.168.1.15 
//192.168.1.20 

При отладке проекта

все задачи выполнять GetFreeDevice функции() в то же время построчно мне нужно сделать задачи ждать, пока текущая GetFreeDevice() выполнение функции сделал .. или любая вещь полезна

СПАСИБО ВСЕ

+1

Тогда не использовать задачи, если вам необходимо последовательное выполнение, просто называют 'GetFreeDevice()' внутри цикла. –

+2

Наличие 'static async void Main (string [] args)' не работает так, как вы думаете, что работает. вы не можете выполнить функцию «Main» async. –

ответ

0

попробовать:

public static Device GetFreeDevice() 
    { 
     List<Device> OnlineDevices = new List<Device>() 
     { 
      new Device { IP="192.168.1.15",Name="PerryLabtop",MAC="AC:DS:F2:CC:2D:7A"}, 
      new Device { IP="192.168.1.20",Name="MAYA-PC",MAC="7D:E9:2C:FF:E7:2D"}, 
      new Device { IP="192.168.1.2",Name="server",MAC="D8:C2:A4:DC:E5:3A"} 
     }; 

     Device FreeDevice = OnlineDevices.Where(x => !UsedDevices.Contains(x)).SingleOrDefault(); 
     if (FreeDevice != null) 
      lock (UsedDevices) 
       UsedDevices.Add(FreeDevice); 
     return FreeDevice; 
    } 

------------------------ UPDATE

попробовать:

public static Device GetFreeDevice() 
    { 
     List<Device> OnlineDevices = new List<Device>() 
     { 
      new Device { IP="192.168.1.15",Name="PerryLabtop",MAC="AC:DS:F2:CC:2D:7A"}, 
      new Device { IP="192.168.1.20",Name="MAYA-PC",MAC="7D:E9:2C:FF:E7:2D"}, 
      new Device { IP="192.168.1.2",Name="server",MAC="D8:C2:A4:DC:E5:3A"} 
     }; 

     lock (UsedDevices) 
     { 
      Device FreeDevice = OnlineDevices.Where(x => !UsedDevices.Contains(x)).SingleOrDefault(); 
      if (FreeDevice != null) 
       UsedDevices.Add(FreeDevice); 
     } 
     return FreeDevice; 
    } 
+0

Вам нужно заблокировать запись ** и ** читать в UsedDevices в этом случае –

+0

@SirRufo спасибо, моя ошибка. – Cologler

+0

Большое спасибо –

4

Несколько проблем должны быть решены, чтобы заставить его работать правильно:

  1. Вы, вероятно, обращенную состояние в for цикле, так как INT I = 2; i == 0; i-- ничего не сделает. Заменить i == 0 с i != 0

  2. async Основной метод не имеет смысла (см, например this blog) и на самом деле даже не компилировать в Visual Studio. Чтобы это исправить, вы можете, например, ждать задач завершить синхронно (использование .Wait() вместо await)

  3. Чтобы предотвратить несколько потоков для выполнения GetFreeDevice() метода одновременно, просто поместите блокировку вокруг кода, который использует общие объекты - который является целым методом тела в вашем случае.

  4. Поскольку вы создаете новый список OnlineDevices каждый раз GetFreeDevice() метод вызывается, UsedDevices.Contains (х) не будет работать, как ожидалось. По умолчанию объекты сравниваются по их ссылке. Так .Contains (х) сравнит Device объектов в UsedDevices список (которые были поставлены там, в одном из предыдущих вызовов) с недавно созданными устройствами объектов, которые никогда не будут равны (ссылки из этих объектов будут разные, несмотря на IP, Название и MAC одинаково). Чтобы это исправить, можно либо переопределить Equals() и GetHashCode() методов на устройстве класса, или (как я сделал) создать только один статический список устройств объектов.

  5. Вы должны заменить SingleOrDefault() с FirstOrDefault()SingleOrDefault() программа будет выбрасывать исключение, если имеется более одного неиспользуемого устройства, тогда как FirstOrDefault() займет первое неиспользуемое устройство, даже если его несколько.

Полный исходный код всех предлагаемых исправлений:

namespace ITDevices 
{ 
    /*Device Modal*/ 
    public class Device 
    { 
     public string IP { get; set; } 
     public string Name { get; set; } 
     public string MAC { get; set; } 
    } 

    /*Entry Class*/ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Task<Device>> Tasks = new List<Task<Device>>(); 

      for (int i = 2; i != 0; i--) 
      { 
       Tasks.Add(Task.Factory.StartNew<Device>(
        () => { 
         Device free = Helper.GetFreeDevice(); 
         return free; 
        } 
        )); 
      } 
      Task.WhenAll(Tasks.ToArray()).Wait(); 
      foreach (Task<Device> item in Tasks) 
      { 
       Console.WriteLine(item.Result.IP); 
      } 
      Console.ReadLine(); 
     } 
    } 
    /*Devices Helper*/ 
    static class Helper 
    { 
     public static List<Device> UsedDevices = new List<Device>(); 

     static List<Device> OnlineDevices = new List<Device>() 
     { 
      new Device { IP="192.168.1.15",Name="PerryLabtop",MAC="AC:DS:F2:CC:2D:7A"}, 
      new Device { IP="192.168.1.20",Name="MAYA-PC",MAC="7D:E9:2C:FF:E7:2D"}, 
      new Device { IP="192.168.1.2",Name="server",MAC="D8:C2:A4:DC:E5:3A"} 
     }; 

     static Object LockObject = new Object(); 

     public static Device GetFreeDevice() 
     { 
      lock (LockObject) 
      { 
       Device FreeDevice = OnlineDevices.Where(x => !UsedDevices.Contains(x)).FirstOrDefault(); 
       if (FreeDevice != null) 
        UsedDevices.Add(FreeDevice); 
       return FreeDevice; 
      } 
     } 
    } 
} 
+0

Это очень полезно благодаря некоторым ошибкам, потому что это виртуальный код, чтобы объяснить, что мне нужно, и реальный код очень сложный –

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