簡體   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