[英]Parallel.Foreach loop never ends
我的代碼在較小的循環上可以按預期執行,但是當我遍歷較大的IP范圍時,該過程似乎會短暫停止並且永遠不會完成。
該程序將繼續運行,並且不會引發任何異常。
public void Discover()
{
Int32 MaxThreadCount = 20,
DevicesProcessed = 0;
List<String> IPAddresses = GetIPAddresses(IPRangesToCheck).ToList();
using (cts = new CancellationTokenSource())
{
ParallelOptions po = new ParallelOptions();
po.MaxDegreeOfParallelism = MaxThreadCount;
po.CancellationToken = cts.Token;
try
{
var deviceInfo = new DeviceInfo();
Parallel.ForEach(IPAddresses, po, (item, loopState) =>
{
try
{
Console.WriteLine("DevicesProcessed: {0}, IPAddresses.Count: {1}", DevicesProcessed, IPAddresses.Count.ToString());
if (DevicesProcessed >= IPAddresses.Count)
{
Console.WriteLine("!!!THRESHOLD REACHED!!!");
cts.Cancel();
}
if (loopState.ShouldExitCurrentIteration || loopState.IsExceptional)
{
loopState.Stop();
DiscoverStatus = Devices.DiscoverState.Stopped;
}
var response = CheckIPAndReturnInfo(item);
if (loopState.ShouldExitCurrentIteration || loopState.IsExceptional)
{
loopState.Stop();
DiscoverStatus = Devices.DiscoverState.Stopped;
}
if (response != null)
{
FoundDevices.Add(response);
Console.WriteLine(
"Device Count {0}, IP Address {1}",
DevicesProcessed,
item);
}
Interlocked.Increment(ref DevicesProcessed);
}
catch (Exception ex)
{
Console.Write("Error! = " + ex.Message);
if (deviceInfo.State == CommunicationState.Faulted)
{
loopState.Stop();
}
}
});
RaiseAllItemsCompleteEvent();
}
catch (AggregateException aggEx)
{
Console.WriteLine("Parrallel Exception!: " + aggEx);
}
}
}
當我使用172.16.0.0到172.16.255.255范圍時,有65536個IP地址需要檢查。 在停止處理更多的地址之前,程序進入65519,並且在代碼中未進行進一步的處理。 此時,在代碼中的任何地方都沒有命中斷點。
if (DevicesProcessed >= IPAddresses.Count)
部分是嘗試在循環結束后手動取消該循環,但是不幸的是,循環並沒有走多遠。 在此之前,請先取消操作。
我一直找不到其他人遇到與此並行任務有關的問題,對此我感到很沮喪。 關於進一步調試問題的方法的任何建議將不勝感激。
我在CheckIPAndReturnInfo
類中添加了一個秒表,以查看經過多長時間。 這是生成“ Start:
和“ End:
輸出文本的地方。 這是程序輸出的輸出示例:
DevicesProcessed: 65515, IPAddresses.Count: 65536
Start : 172.16.114.94
End : 172.16.114.94 Elaspsed: 00:00:01.4247110
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
End : 172.16.114.60 Elaspsed: 00:00:07.0803977
DevicesProcessed: 65517, IPAddresses.Count: 65536
Start : 172.16.114.61
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
End : 172.16.114.76 Elaspsed: 00:00:07.0807436
DevicesProcessed: 65518, IPAddresses.Count: 65536
Start : 172.16.114.77
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
The thread '<No Name>' (0x1664) has exited with code 0 (0x0).
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
End : 172.16.114.61 Elaspsed: 00:00:07.0806001
DevicesProcessed: 65519, IPAddresses.Count: 65536
Start : 172.16.114.62
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
End : 172.16.114.77 Elaspsed: 00:00:07.0807928
DevicesProcessed: 65520, IPAddresses.Count: 65536
Start : 172.16.114.78
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
The thread '<No Name>' (0xf90) has exited with code 0 (0x0).
The thread '<No Name>' (0x1b24) has exited with code 0 (0x0).
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
End : 172.16.114.62 Elaspsed: 00:00:07.0806679
A first chance exception of type 'Lextm.SharpSnmpLib.Messaging.TimeoutException' occurred in SharpSnmpLib.dll
End : 172.16.114.78 Elaspsed: 00:00:07.0804395
The thread '<No Name>' (0x1518) has exited with code 0 (0x0).
The thread '<No Name>' (0x1e1c) has exited with code 0 (0x0).
The thread '<No Name>' (0x1190) has exited with code 0 (0x0).
The thread '<No Name>' (0x1218) has exited with code 0 (0x0).
The thread '<No Name>' (0x1c68) has exited with code 0 (0x0).
The thread '<No Name>' (0x1b20) has exited with code 0 (0x0).
The thread '<No Name>' (0xa14) has exited with code 0 (0x0).
The thread '<No Name>' (0x185c) has exited with code 0 (0x0).
The thread '<No Name>' (0x430) has exited with code 0 (0x0).
不要在if語句中使用IsCompleted
。 只要把RaiseAllItemsCompleteEvent
后Parallel.ForEach
。
在您的異常處理程序中,請勿重新引發異常,因為這將導致Parallel
出錯。 只需使用loopState.Stop
。
愚蠢的例子:
Parallel.ForEach(Enumerable.Range(0, 100),
(i, state) =>
{
Console.WriteLine(i);
if(i==11) state.Stop();
});
RaiseAllItemsCompleteEvent();
在條件檢查中,只需使用if(loopState.IsStopped)
。 給定您的try/catch
塊,很難擊中IsExceptional
。
最后,因為您正在並行運行,所以必須使用Interlocked.Increment(ref DevicesProcessed)
。 否則,計數將不准確。
cts.Cancel()
可以拋出AggregateException
也可以在內部嘗試捕獲它,看看它是否命中,如果這是在您當前的代碼中沒有內部`AggregateException'發生的,它將進入無限循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.