我正在使用Parallel.Invoke
同时运行某些方法并在所有方法完成后收集结果。
问题
正如您在“可怕的代码”部分看到的那样,动作列表被硬编码为三个元素,如果detectedDevicesList.Count != 3
.
尝试过的解决方案
我尝试动态创建一个Actions[]
数组并将其作为参数传递给Parallel.Invoke
,但我无法将现有方法转换为Task
s,然后再转换为Action
s。
非工作代码
public async Task<Task<String>> callWithEveryConnectedDevice(ListBox listBoxLog, Boolean sendAlarms)
{
String TEST_CALLS_COMPLETED = "All test calls completed.";
String TEST_CALLS_FAILED = "One or more test cals failed";
return Task.Run(async () =>
{
List<MobileEquipment> detectedDevicesList = await GetConnectedDevices.getAsync();
if (detectedDevicesList.Count == 0)
{
UpdateGui.listboxAddItem(listBoxLog, "No devices are connected.", true);
return TEST_CALLS_FAILED;
}
Console.WriteLine("Executing test calls...");
List<Task<MobileEquipment>> results = new List<Task<MobileEquipment>>();
//Horrible code begins...
Parallel.Invoke(() =>
{
results.Add(new MakePhoneCall().call(detectedDevicesList[0], listBoxLog));
},
() =>
{
results.Add(new MakePhoneCall().call(detectedDevicesList[1], listBoxLog));
},
() =>
{
results.Add(new MakePhoneCall().call(detectedDevicesList[2], listBoxLog));
});
//Horrible code ends...
foreach (Task<MobileEquipment> mobileEquipment in results)
{
UpdateGui.listboxAddItem(listBoxLog, "Test call result for " + mobileEquipment.Result.serial + " " + mobileEquipment.Result.operador + ": " + mobileEquipment.Result.callSuccess, true);
if (!mobileEquipment.Result.callSuccess && sendAlarms)
{
await SendEmail.sendAlarmEmailsAsync(libreta, asunto, mensaje);
}
}
UpdateGui.listboxAddItem(listBoxLog, TEST_CALLS_COMPLETED, true);
return TEST_CALLS_COMPLETED;
});
}
编辑:给读者的有用信息和经验教训
在收到出色的答案和评论之后,我添加了一些最初缺失的代码,这些代码可以帮助您安全地与并行任务中的 Windows 窗体对象进行交互。
public static void ListboxAddItem(ListBox listBox, String argText, Boolean useTimestamp)
{
String timeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
if (useTimestamp)
{
argText = timeStamp + ": " + argText;
}
if (Thread.CurrentThread.IsBackground)
{
listBox.Invoke(new Action(() =>
{
listBox.Items.Add(argText);
listBox.SelectedIndex = listBox.Items.Count - 1;
}));
}
else
{
listBox.Items.Add(argText);
listBox.SelectedIndex = listBox.Items.Count - 1;
}
}
此外,不要盲目遵循 IntelliSense 建议,以防止像 Task<Task> 这样的恶作剧,或在 C# 上使用类似 Java 的大小写。
很难选择最佳建议的答案,因为它们都可以正常工作并且没有任何明显的性能差异(MakePhoneCall().call 使用通过 ADB 连接的 Android 设备进行自动电话呼叫)。检查哪个答案最适合您的特定应用。