C#运行时动态调整Parallel.Invoke操作的实现问题咨询
问题背景
你当前的核心需求是让Parallel.Invoke的入参适配任意数量的已连接设备,避免硬编码3个元素的问题,同时我们也可以顺便优化现有代码里的其他不合理写法。
最佳解决方案
你这里的场景完全不需要用Parallel.Invoke,因为MakePhoneCall.call本身是返回Task<MobileEquipment>的异步方法,属于IO密集型任务,直接用Task.WhenAll处理更简单高效,适配任意数量设备的代码修改如下:
public async Task<String> CallWithEveryConnectedDevice(ListBox listBoxLog, bool sendAlarms) { const string TEST_CALLS_COMPLETED = "所有测试呼叫已完成"; const string TEST_CALLS_FAILED = "部分测试呼叫失败"; List<MobileEquipment> detectedDevicesList = await GetConnectedDevices.getAsync(); if (detectedDevicesList.Count == 0) { UpdateGui.listboxAddItem(listBoxLog, "无已连接设备", true); return TEST_CALLS_FAILED; } Console.WriteLine("正在执行测试呼叫..."); // 直接遍历设备列表生成所有拨号任务,没有数量限制 List<Task<MobileEquipment>> callTasks = detectedDevicesList .Select(device => new MakePhoneCall().call(device, listBoxLog)) .ToList(); // 等待所有拨号任务执行完成 await Task.WhenAll(callTasks); // 处理所有返回结果 foreach (var equipmentTask in callTasks) { // 用await替代Result避免阻塞和死锁风险 MobileEquipment equipment = await equipmentTask; UpdateGui.listboxAddItem(listBoxLog, $"设备 {equipment.serial}(运营商:{equipment.operador})的测试呼叫结果:{equipment.callSuccess}", true); if (!equipment.callSuccess && sendAlarms) { await SendEmail.sendAlarmEmailsAsync(libreta, asunto, mensaje); } } UpdateGui.listboxAddItem(listBoxLog, TEST_CALLS_COMPLETED, true); return TEST_CALLS_COMPLETED; }
原有代码的问题说明
- 嵌套Task返回值:原写法
async Task<Task<String>>属于不必要的嵌套Task,直接用Task<String>作为返回值即可,也不需要外层套Task.Run。 - 线程安全问题:
List<T>不是线程安全的集合,你在Parallel.Invoke的多线程委托里直接调用Add方法,可能会出现丢数据、索引异常的问题。 - API选型错误:
Parallel.Invoke是为CPU密集型并行场景设计的API,你这里的拨号、ADB操作都属于IO密集型任务,用Task.WhenAll更节省线程资源,性能更好。
如果你一定要用Parallel.Invoke的实现方案
如果业务要求必须用Parallel.Invoke,可以按如下方式动态生成Action数组,注意要加锁保证集合操作的线程安全:
List<Task<MobileEquipment>> results = new List<Task<MobileEquipment>>(); // 动态生成Action数组 Action[] invokeActions = detectedDevicesList .Select<MobileEquipment, Action>(device => () => { // 加锁避免多线程操作List的异常 lock(results) { results.Add(new MakePhoneCall().call(device, listBoxLog)); } }) .ToArray(); Parallel.Invoke(invokeActions);
内容的提问来源于stack exchange,提问作者Felipe La Rotta
相关产品推荐
相关产品推荐

