将异常从Task.Run传递到等待正确和调试器

时间:2016-06-17 20:12:00

标签: c# exception async-await task-parallel-library task

这是抛出异常的任务。

public Task<SensorReading> ReadSensorsAsync(int cell)
{
    return Task.Run(() => {
            throw new ArgumentNullException();
...

这是async方法:

private async void TimerCallback(object state)
{
    try
    {
        var tasksRead = Enumerable.Range(3, 35).Select(i => sensorReader.ReadSensorsAsync(i)).ToList();
        await Task.WhenAll(tasksRead);
        var r = tasksRead.Select(x => x.Result).ToList();
        var taskRecordREsult = RecordReadingAsync(r).Result;
    }
    catch(Exception e)
    {
        // expecting to catch everything here
    }
}

我期待的是异常将在await部分代码中处理。但是,我在Visual Studio调试器中遇到未处理的异常。

问题 - 如何正确地将所有类型的异常从Task.Run传递给等待的部分?

2 个答案:

答案 0 :(得分:0)

一种可能的解决方案是将Task.Run lambda解压缩为独立方法,并为其添加[DebuggerStepThrough]属性。理论上(我还没有对此进行测试),这将抑制调试器中的第一个异常,并允许稍后捕获它。它并不漂亮,但应该可以解决这个问题。

答案 1 :(得分:0)

尝试这个程序,看看你是否还在破碎......

为我工作

class Program
{
    static void Main(string[] args)
    {
        new Program().TimerCallback();
    }

    public Task<string> ReadSensorsAsync(string cell)
    {
        return Task.Run(() =>
        {
            if(cell == null) throw new ArgumentNullException();
            return cell;
        });
    }

    public Task<string> RecordReadingAsync(IEnumerable<string> cell)
    {
        return Task.Run(() =>
        {
            return string.Join(",", cell);
        });
    }

    public async void TimerCallback()
    {
        try
        {
            var tasksRead = new string[] { "1", null, "3" }.Select(s => ReadSensorsAsync(s));
            var taskRecordResult = await RecordReadingAsync(await Task.WhenAll(tasksRead));
            Debugger.Log(1, "test", taskRecordResult);
        }
        catch (Exception e)
        {
            //catches here
            Debugger.Log(1, "test", e.Message ?? e.ToString());
        }
    }
}