繁体   English   中英

任务吞下抛出的异常

[英]Task swallows the exception thrown

下面的方法中,当TRY块中抛出异常时,就是被吞了。 我怎样才能让它抛出异常,以便它被写入以登录 catch 块? 日志编写器工作正常。 谢谢!

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;
}

如果您想触发并忘记,您可以使用ContinueWith附加一个延续。 当前的try-catch根本不会帮助您,因为异常被封装在Task 如果这是“即发即弃”,那么您可以记录异常:

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); 
}

反过来,这不会在抛出异常后传播异常,但会提供一种记录错误的机制。 如果您希望异常得到正确处理,您可以注册到TaskScheduler.UnobservedTaskException 此外,如果您希望未处理的异常终止您的应用程序,您可以在配置中设置ThrowUnobservedTaskExceptions enabled="true" 一旦您查看task.Exception属性, ContinueWith将考虑“已处理”异常。

异常不被吞下; 只是它不会发生在执行 try/catch 块的线程上,而是发生在单独的 Task 线程上。

如果你不观察任务的结果或异常,当任务最终被垃圾回收时,它会抛出一个异常,说任务没有被观察到。 除非您通过处理TaskScheduler.UnobservedTaskException捕获它,否则它会使进程崩溃。

我也有这个问题,我真的不喜欢 App.config 的整个想法,所以可以提供另一种解决方案来防止异常消失:)

保存异常然后在 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