我在这篇文章(http://bytes.com/topic/c-sharp/answers/238006-cannot-catch-exception-thread#post970280)中读到:'抛出异常是堆栈绑定对象。因为每个线程都有它 自己的堆栈,线程A中抛出的异常不能突然出现 线程B'
但我有一个项目,其中似乎恰好发生了这种情况。我有点想要找到问题的根源。我正在做的是调用10个线程,其中每个线程同时运行多个工具。通过在进程中启动可执行文件,每个工具都在另一个线程中运行。这意味着如果我有例如2个工具我将总共有10x2个线程。问题如下:如果抛出异常,例如当其中一个工具线程失败并且我想在同一个线程中捕获它时,会发生任何线程捕获异常。我通过让runTool函数在抛出的异常中包含threadId和toolId并比较throw和catch的输出来让run方法输出验证
这里是简化代码:
class Worker
{
private ManualResetEvent[] threadResetEvents;
private ManualResetEvent[][] toolResetEvents;
private Tool[] tools;
public int stopped = false;
public void run(int threadNo)
{
threadResetEvents = new ManualResetEvent[threadNo];
toolResetEvents = new ManualResetEvent[threadNo][];
for (int i = 0; i < threadNo; i++)
{
threadResetEvents[i] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(fillDb), (object)i);
}
sendToObservers("Filling database...");
WaitHandle.WaitAll(threadResetEvents);
}
private void fillDb(object obj)
{
int threadId = (int)obj;
while (!stopped)
{
toolResetEvents[threadId] = new ManualResetEvent[tools.Length];
for (int i = 0; i < tools.Length; i++)
{
toolResetEvents[threadId][i] = new ManualResetEvent(false);
ToolInfoObject info = new ToolInfoObject(threadId, i);
ThreadPool.QueueUserWorkItem(new WaitCallback(runTool), info);
}
WaitHandle.WaitAll(toolResetEvents[threadId]);
}
}
private void runTool(object obj)
{
ToolInfoObject info = (ToolInfoObject) i;
int threadId = info.threadId;
int toolId = info.toolId;
try
{
tools[toolId].runTool(threadId, toolId);
}
catch (Exception e)
{
Console.WriteLine("Exception caught in Thread " + threadId + ", Tool " + toolId + ": " + e.GetBaseException());
}
}
}
class ToolInfoObject
{
public int threadId;
public int toolId;
public ToolInfoObject(int thread, int tool)
{
this.threadId = thread;
this.toolId = tool;
}
}
我很感激任何帮助
编辑:
更详细地说,抛出IOException时会出现问题。我让每个工具根据线程编号创建一个目录和文件。如果文件不可访问,将导致如下消息:
在线程1,工具0中捕获异常:System.IO.FileNotFoundException:Die Datei“C:\ tmpdir \ 3 \ log.txt”konnte nicht gefunden werden。
这意味着异常实现发生在线程3中,但是在线程1中被捕获
答案 0 :(得分:3)
检查Tool
是否是线程安全的。如果不是这可能会导致您的问题。