一个线程中抛出的c#异常被另一个线程捕获

一个线程中抛出的c#异常被另一个线程捕获,c#,C#,我在这篇文章中读到(http://bytes.com/topic/c-sharp/answers/238006-cannot-catch-exception-thread#post970280)抛出的异常是堆栈绑定对象。因为每一根线都有它自己的特点 在自己的堆栈中,线程A中抛出的异常不能突然出现在 线程B' 但我有一个项目,在这个项目中,这一切似乎都发生了。我有点急于找到问题的根源。我所做的是调用10个线程,其中每个线程同时运行多个工具。通过在进程中启动一个可执行文件,每个工具在另一个线程中运行

我在这篇文章中读到(http://bytes.com/topic/c-sharp/answers/238006-cannot-catch-exception-thread#post970280)抛出的异常是堆栈绑定对象。因为每一根线都有它自己的特点 在自己的堆栈中,线程A中抛出的异常不能突然出现在 线程B'

但我有一个项目,在这个项目中,这一切似乎都发生了。我有点急于找到问题的根源。我所做的是调用10个线程,其中每个线程同时运行多个工具。通过在进程中启动一个可执行文件,每个工具在另一个线程中运行。这意味着如果我有例如2个工具,我总共将有10x2个螺纹。问题如下:如果抛出异常,例如,当一个工具线程失败并且我想在同一个线程内捕获它时,任何线程都会捕获该异常。我通过让runTool函数在抛出的异常中包含threadId和toolId,并比较抛出和捕获的输出,来验证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;
}
}
类工作者
{
private ManualResetEvent[]线程重置事件;
专用手册重置事件[][]工具重置事件;
私人工具[]工具;
public int stopped=false;
公共无效运行(int-threadNo)
{
threadResetEvents=新的ManualResetEvent[threadNo];
toolResetEvents=新的ManualResetEvent[threadNo][];
对于(int i=0;i
如果有任何帮助,我将不胜感激

编辑:

更详细地说,当抛出IOException时,问题就会出现。我让每个工具根据线程号创建一个目录和其中的文件。如果文件不可访问,则会产生如下消息:

线程1中捕获异常,工具0:System.IO.FileNotFoundException:Die Datei“C:\tmpdir\3\log.txt”konnte nicht gefunden werden


这意味着异常实际上发生在线程3中,但在线程1中被捕获。检查
工具是否是线程安全的。如果不是,这可能会导致您的问题。

您使用的是什么版本的框架。4.0使这些东西的一部分成为了
i
的来源(
toolnfoobjectinfo=(toolnfoobject)i
?当使用线程池时,线程将被重用-您将看到不同操作的相同线程Id。这可能是您的问题吗?此代码包含多个错误。因此它不是真实的。我怀疑您的问题也不是真实的。请尝试制作一个完整的小示例并发布。我已经在使用4.0了-ToolInfoObject包含truntool函数的参数-int stopped应该是bool stopped-代码是真实的,尽管这只是简化版(我必须承认有一些错误),但仍然留下了很多空白点。您捕获(并重新抛出)了吗任何时候的异常?涉及任何静态类?工具类根本不与其他线程通信,这是否意味着它是线程安全的?不,简而言之,如果它只使用本地对象并访问其他线程安全方法,那么它是线程安全的。工具类只使用本地对象,但读取文本文件,访问mysql数据库和d在进程中运行一个可执行文件。这可能会导致问题吗?为了线程安全和可重入,您不得访问该类的任何字段,这些字段不是只读的,只能使用其他类的线程安全方法。例如,不允许您在工具类的任何字段值中存储文件名、filestream或threadId,而只能使用local方法中的变量。不,我只看到应该是安全的
tools[toolId]