运行此程序时,有时异常有一个堆栈跟踪,它起源于以“throw new Exception...”开头的行,但有时它有一个堆栈跟踪,起源于 Parallel.For 委托的第一个大括号。为什么会有那个行号?
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System;
public class J
{
public static void Main()
{
ConcurrentDictionary<string, int> exceptions = new ConcurrentDictionary<string, int>();
Parallel.For(0, 10, (i, s) =>
{ //this is line 55
try
{
throw new Exception("blah"); //line 58
}
catch (Exception e)
{
string estring = e.ToString();
exceptions.TryAdd(estring, 0);
lock (exceptions)
{
exceptions[estring] += 1;
}
}
});
foreach (var entry in exceptions)
{
Console.WriteLine("==============" + entry.Value + " times");
Console.WriteLine(entry.Key);
}
}
}
这是奇怪的输出
==============3 times
System.Exception: blah
at J.<>c__DisplayClass5.<Main>b__4(Int32 i, ParallelLoopState s) in Program.cs:line 55
==============7 times
System.Exception: blah
at J.<>c__DisplayClass5.<Main>b__4(Int32 i, ParallelLoopState s) in Program.cs:line 58
Press any key to continue . . .
我修改了代码以在 e.ToString() 之前包含 System.Threading.Thread.CurrentThread.ManagedThreadId。我必须运行它大约 20 次才能重现它,在第 55 行生成异常。从下面的输出中,我可以看到 Goz 是对的;它在一些并行任务中使用了主线程(线程 ID 1),但是它从主线程获得了两次正确的行号,然后从主线程获得了一次错误的行号。所以还是很神秘。
==============3 times
5 - System.Exception: blah
at J.<>c__DisplayClass5.<Main>b__4(Int32 i, ParallelLoopState s) in Program.cs:line 58
==============1 times
6 - System.Exception: blah
at J.<>c__DisplayClass5.<Main>b__4(Int32 i, ParallelLoopState s) in Program.cs:line 58
==============2 times
1 - System.Exception: blah
at J.<>c__DisplayClass5.<Main>b__4(Int32 i, ParallelLoopState s) in Program.cs:line 58
==============1 times
1 - System.Exception: blah
at J.<>c__DisplayClass5.<Main>b__4(Int32 i, ParallelLoopState s) in Program.cs:line 55
==============2 times
4 - System.Exception: blah
at J.<>c__DisplayClass5.<Main>b__4(Int32 i, ParallelLoopState s) in Program.cs:line 58
==============1 times
3 - System.Exception: blah
at J.<>c__DisplayClass5.<Main>b__4(Int32 i, ParallelLoopState s) in Program.cs:line 58
Press any key to continue . . .