我对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()函数执行完成等待任务...或任何有用的事情
感谢所有
答案 0 :(得分:4)
必须解决几个问题才能使其正常运行:
你可能在for
循环中颠倒了条件,因为 int i = 2;我== 0;我 - 什么都不做。将i == 0
替换为i != 0
async
主要方法没有意义(例如参见this blog),实际上甚至无法在Visual Studio中编译。要解决此问题,您可以等待任务同步完成(使用.Wait()
代替await
)
为防止多个线程同时运行 GetFreeDevice()方法,只需将锁定放在使用共享对象的代码周围 - 在您的情况下就是整个方法体。
因为每次调用 GetFreeDevice()方法时都会创建 OnlineDevices 的新列表,所以 UsedDevices.Contains(x)将会不按预期工作。默认情况下,对象按其引用进行比较。所以 .Contains(x)将比较 UsedDevices 列表中的 Device 对象(这些对象是在之前的一个调用中放置的)与新创建的设备对象,永远不会相等(尽管 IP ,名称和 MAC 是这些对象的引用会有所不同相同)。要解决此问题,您可以在 Device 类上覆盖 Equals()和 GetHashCode()方法,或者(就像我一样)只创建一个设备对象的静态列表。
您必须将 SingleOrDefault()替换为 FirstOrDefault()。使用 SingleOrDefault(),如果有多个未使用的设备,程序将抛出异常,而 FirstOrDefault()将使用第一个未使用的设备,即使有多个未使用的设备。< / p>
包含所有建议修补程序的完整源代码:
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;
}