并行任务调用静态函数



我对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. 您可能在for循环中颠倒了条件,因为int i=2;i==0;我什么也不做。用i != 0替换i == 0

  2. asyncMain方法没有意义(例如,请参阅本博客),实际上甚至不能在Visual Studio中编译。要解决此问题,例如,您可以等待任务同步完成(使用.Wait()而不是await)

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

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

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

try:

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

------------------------更新

尝试:

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

最新更新