【问题标题】:Catching an exception thrown in a Thread捕获线程中抛出的异常
【发布时间】:2018-06-20 21:46:44
【问题描述】:

我需要知道在线程调用的方法中发生的异常是否可以在主应用程序中捕获。 我正在做一个 Windows 窗体应用程序,我必须做的一件事是将一些数据存储在数据库中,但如果由于某种原因操作不成功(例如,如果应用程序不能连接到数据库)。问题是我必须调用该方法以从新线程将值插入数据库中,因此,我使用 try;catch 来自该方法内部的块。但是,如果发生错误并引发异常,则没有人能够捕获它,因此程序崩溃。 我一直在做一些谷歌搜索,但我能找到的所有内容都建议使用类 Task 而不是 Thread,但是,因为这是我大学的作业,我需要使用 Threads。

那么,有没有办法将异常从线程“转移”到应用程序的主线程?到目前为止,这是我的代码:

    //This is how I create the new Thread
    public static Correo operator +(Correo c, Paquete p)
    {
        foreach (Paquete paq in c.Paquetes)
        {
            if (paq == p)
                throw new TrackingIDRepetidoException("El paquete ya se encuentra cargado en la base de datos");
        }
        c.Paquetes.Add(p);
        Thread hilo = new Thread(p.MockCicloDeVida);
        hilo.Start();
        c.mockPaquetes.Add(hilo);
        return c; 
    }


    public void MockCicloDeVida()
    {
        while (this.Estado != EEstado.Entregado)
        {
            Thread.Sleep(10000);
            this.Estado += 1;
            this.InformaEstado(this, new EventArgs());
        }
        try
        {
            // A simple method to insert an object in a DB. The try catch to check if the connection to the DB was succesfull or not is implemented here.
            PaqueteDAO.Insertar(this);
        }
        catch (System.Data.SqlClient.SqlException e)
        {
            // I can't catch the exception here
        }
    }

非常感谢任何帮助或提示。谢谢!

【问题讨论】:

  • 您使用Thread 而不是Task 是否有特殊原因?
  • Thread 用于即发即弃线程,您不希望线程有任何响应,包括如果它有错误。如果您想要回复,您应该使用BackgroundWorkerTask
  • 这是我大学的作业,他们强迫我使用线程。
  • 基本上,没有。异常是一种基于堆栈的机制,每个线程都有自己的堆栈。
  • 那会很痛苦;您必须使用 IPC,例如管道或消息队列。您也许可以从WaitHandles 构建一些东西;我不想。

标签: c# multithreading thread-safety


【解决方案1】:

我会使用这个非常有用的类:TaskCompletionSource

var tcs = new TaskCompletionSource<object>();
var th = new Thread(() => MockCicloDeVida(tcs));
th.Start();
try
{
    var returnedObj = tcs.Task.Result;
}
catch(AggregateException aex)
{
    Console.WriteLine(aex.InnerExceptions.First().Message);
}

public void MockCicloDeVida(TaskCompletionSource<object> tcs )
{
    Thread.Sleep(10000);
    tcs.TrySetException(new Exception("something bad happened"));
    //tcs.TrySetResult(new SomeObject());
}

【讨论】:

    猜你喜欢
    • 2011-08-24
    • 2011-12-05
    • 1970-01-01
    • 2012-06-08
    • 2014-05-20
    • 2011-06-25
    • 2013-06-24
    • 2013-06-16
    • 2017-10-14
    相关资源
    最近更新 更多