简体   繁体   English

任务吞下抛出的异常

[英]Task swallows the exception thrown

In the method below, when an exception is thrown in the TRY block, it is being swallowed.下面的方法中,当TRY块中抛出异常时,就是被吞了。 How can I make it throw the exception so that it gets written to log in the catch block?我怎样才能让它抛出异常,以便它被写入以登录 catch 块? The log writer works fine.日志编写器工作正常。 Thanks!谢谢!

public static bool MonitorQueueEmptyTask(string queueName, CancellationTokenSource tokenSource)
{
    try
    {
        Task<bool> task = Task.Factory.StartNew<bool>(() =>
        {
            while (!QueueManager.IsQueueEmpty(queueName))
            {
                if (tokenSource.IsCancellationRequested)
                {                            
                    break;
                }

                Thread.Sleep(5000);
                throw new Exception("Throwing an error!"); //THIS THROW IS SWALLOWED -- NO LOG WRITTEN ON CATCH
            };

            return true;

        }, tokenSource.Token);
    }
    catch (Exception ex)
    {   
        WriteExceptionToLog(ex.Stack); //it's not that this method doesn't work. it works fine.

        return false;
    }

    return true;
}

If you want to fire and forget, you can attach a continuation using ContinueWith .如果您想触发并忘记,您可以使用ContinueWith附加一个延续。 The current try-catch will not help you at all, as the exception is encapsulated inside the Task .当前的try-catch根本不会帮助您,因为异常被封装在Task If this is "fire and forget", than you can log the exception:如果这是“即发即弃”,那么您可以记录异常:

public static Task MonitorQueueEmptyTask(
                         string queueName, CancellationTokenSource tokenSource)
{
    return Task.Factory.StartNew<bool>(() =>
    {
        while (!QueueManager.IsQueueEmpty(queueName))
        {
            if (tokenSource.IsCancellationRequested)
            {                            
                break;
            }

            Thread.Sleep(5000);
            throw new Exception("Throwing an error!");
        };
    }, tokenSource.Token, TaskCreationOptions.LongRunning).ContinueWith(faultedTask =>
    {
        WriteExceptionToLog(faultedTask.Exception); 
    }, TaskContinuationOptions.OnlyOnFaulted); 
}

This, in turn, will not propagate the exception after it's thrown, but will provide a mechanism to log the error.反过来,这不会在抛出异常后传播异常,但会提供一种记录错误的机制。 If you want the exception to be properly handled, you can register to TaskScheduler.UnobservedTaskException .如果您希望异常得到正确处理,您可以注册到TaskScheduler.UnobservedTaskException Additionally, you can set ThrowUnobservedTaskExceptions enabled="true" in your configuration if you want unhandled exceptions to terminate your application.此外,如果您希望未处理的异常终止您的应用程序,您可以在配置中设置ThrowUnobservedTaskExceptions enabled="true" ContinueWith will consider the exception "handled" once you look at the task.Exception property.一旦您查看task.Exception属性, ContinueWith将考虑“已处理”异常。

The exception is not swallowed;异常不被吞下; it's just that it doesn't occur on the thread that executes the try/catch block, but on the separate Task thread.只是它不会发生在执行 try/catch 块的线程上,而是发生在单独的 Task 线程上。

If you don't observe the task's result or exception, when the task is eventually garbage collected, it will throw an exception saying that the task was not observed.如果你不观察任务的结果或异常,当任务最终被垃圾回收时,它会抛出一个异常,说任务没有被观察到。 Unless you catch that by handling the TaskScheduler.UnobservedTaskException , it will crash the process.除非您通过处理TaskScheduler.UnobservedTaskException捕获它,否则它会使进程崩溃。

I also had a problem with this, and i really dislike the whole idea of App.config, so can provide another solution to prevent the exceptions disappearing :)我也有这个问题,我真的不喜欢 App.config 的整个想法,所以可以提供另一种解决方案来防止异常消失:)

Save the exception then throw it after the Task.Run has completed, eg保存异常然后在 Task.Run 完成后抛出它,例如

private async void Function() {
    Exception save_exception = null;

    await Task.Run(() => {
        try {
            // Do Stuff
        } catch (Exception ex) {
            save_exception = ex;
        }
    }).ContinueWith(new Action<Task>(task => {
        if (save_exception != null)
            throw save_exception;

        // Do Stuff 
    }));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM