Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Task.Factory时捕获错误_C#_.net_Multithreading - Fatal编程技术网

C# 使用Task.Factory时捕获错误

C# 使用Task.Factory时捕获错误,c#,.net,multithreading,C#,.net,Multithreading,我正在使用下面的 Task.Factory.StartNew(() => DoPrintConfigPage(serial)); 那么我调用的函数如下所示 private void DoPrintConfigPage(string serial) { //do printing work } 我的问题是一个异常被抛出线程内部而没有被处理 我试过把它包在一个试扣里 try { Task.Factory.StartNew(() => DoPrintConfigP

我正在使用下面的

Task.Factory.StartNew(() => DoPrintConfigPage(serial));
那么我调用的函数如下所示

private void DoPrintConfigPage(string serial) 
{ 
    //do printing work 
}
我的问题是一个异常被抛出线程内部而没有被处理

我试过把它包在一个试扣里

try
{
    Task.Factory.StartNew(() => DoPrintConfigPage(serial));
}
catch (Exception ex) { }
但它仍然无法捕获错误,从而导致应用程序崩溃

如何在主线程中捕获异常以便处理它们

更新 我已经做了下面建议的更改,但仍然表示异常未处理

var task =  Task.Factory.StartNew(() => DoPrintConfigPage(serial))
                               .ContinueWith(tsk =>
                               {
                                  MessageBox.Show("something broke");
                               },TaskContinuationOptions.OnlyOnFaulted);
然后在我的
DoConfigPage
中添加了另一个try-catch

在这个catch中,它现在崩溃了,并说抛出的异常未经处理,我遗漏了什么

private void DoPrintConfigPage(string serial)
{
    try
    {
        //call the print function
    }
    catch (Exception ex)
    {
        throw ex;   //it is crashing here and saying it is unhandled
    }
}
我也尝试了Eric J.的建议,得到了同样的结果

var task = Task.Factory.StartNew(() => DoPrintConfigPage(serial));

try
{
    task.Wait();                  
}
catch (AggregateException ex) { MessageBox.Show("something broke"); }

您的
try
块在启动新任务后立即退出,因为该方法将继续运行

相反,您可以将异常捕获为等待任务(或多个任务)完成的时间:

var task1 = Task.Factory.StartNew(() =>
{
    throw new MyCustomException("I'm bad, but not too bad!");
});

try
{
    task1.Wait();
}
catch (AggregateException ae)
{
    // Assume we know what's going on with this particular exception. 
    // Rethrow anything else. AggregateException.Handle provides 
    // another way to express this. See later example. 
    foreach (var e in ae.InnerExceptions)
    {
        if (e is MyCustomException)
        {
            Console.WriteLine(e.Message);
        }
        else
        {
            throw;
        }
    }

}

你也应该知道


如果您正在创建“启动并忘记”任务实例,您将希望在程序开始时订阅该事件。

或者,您可以链接任务创建并添加一个ContinueWith:

var job = Task.Factory
    .StartNew(...)
    .ContinueWith(tsk => 
         {
              // check tsk for exception and handle
         });
编辑:运行此代码段时,会为我弹出消息框:

void Main()
{
    var serial = "some serial";
    var task =  Task.Factory
        .StartNew(() => DoPrintConfigPage(serial))
        .ContinueWith(tsk =>
        {
            MessageBox.Show("something broke");
            var flattened = tsk.Exception.Flatten();

            // NOTE: Don't actually handle exceptions this way, m'kay?
            flattened.Handle(ex => { MessageBox.Show("Error:" + ex.Message); return true;});
        },TaskContinuationOptions.OnlyOnFaulted);

}

public void DoPrintConfigPage(string serial)
{
    throw new Exception("BOOM!");
}

如果您没有等待任务,我认为最简单的解决方案是:

获取导致任务提前结束的AggregateException。 如果任务已成功完成或尚未抛出任何 异常时,将返回null

我用的是这样的东西:

Task.Factory.StartNew(() => DoStuffHere())
    .ContinueWith(task =>
    {
        if (task.Exception != null)
            Log("log all the exceptions!");
    });

也许你是想抓住一个机会。因为.NET 4应用程序在默认情况下无法捕获此类异常。您可以尝试将
legacyCorruptedState­ExceptionsPolicy=true
条目添加到您的配置文件中,如上面链接的MSDN文章所述。

值得注意的是
TaskContinuationOptions。您只能添加一个有故障的
参数,以便仅在出现异常时运行继续,有效地使它像一个
catch
块。@servy Good call;我总是忘记看到更新的代码,我尝试了这个,但它仍然没有处理它。这不是你想要做的-你现在所做的只是在继续中抛出一个不同的异常;如果您想处理延续本身中的任何异常,请选中
Task.IsFaulted
,然后选择
Exception
属性-但无论如何,您仍然是
try
/
catch
位于错误的位置-您将包装等待任务完成的内容,不是创建的。谢谢我得到了它。它在调试时仍然显示未处理的异常,但在运行“不调试”时,它工作得很好,完成了我需要它做的事情。谢谢你的帮助!