并行任务调用静态函数

时间:2016-12-31 16:48:35

标签: c# task

我对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()函数执行完成等待任务...或任何有用的事情

感谢所有

2 个答案:

答案 0 :(得分:4)

必须解决几个问题才能使其正常运行:

  1. 你可能在for循环中颠倒了条件,因为 int i = 2;我== 0;我 - 什么都不做。将i == 0替换为i != 0

  2. async主要方法没有意义(例如参见this blog),实际上甚至无法在Visual Studio中编译。要解决此问题,您可以等待任务同步完成(使用.Wait()代替await

  3. 为防止多个线程同时运行 GetFreeDevice()方法,只需将锁​​定放在使用共享对象的代码周围 - 在您的情况下就是整个方法体。

  4. 因为每次调用 GetFreeDevice()方法时都会创建 OnlineDevices 的新列表,所以 UsedDevices.Contains(x)将会不按预期工作。默认情况下,对象按其引用进行比较。所以 .Contains(x)将比较 UsedDevices 列表中的 Device 对象(这些对象是在之前的一个调用中放置的)与新创建的设备对象,永远不会相等(尽管 IP 名称 MAC 是这些对象的引用会有所不同相同)。要解决此问题,您可以在 Device 类上覆盖 Equals() GetHashCode()方法,或者(就像我一样)只创建一个设备对象的静态列表。

  5. 您必须将 SingleOrDefault()替换为 FirstOrDefault()。使用 SingleOrDefault(),如果有多个未使用的设备,程序将抛出异​​常,而 FirstOrDefault()将使用第一个未使用的设备,即使有多个未使用的设备。< / p>

  6. 包含所有建议修补程序的完整源代码:

    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;
                }
            }
        }
    }
    

答案 1 :(得分: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;
    }