Exception handling outside of Task

白昼怎懂夜的黑 提交于 2019-12-30 11:49:41

问题


Just noticed strange thing: to catch exception in caller from new Task, lambda MUST be marked as async!? Is it really necessary even if delegate has no await operators at all?

    try
    {
        //Task.Run(() =>      // exception is not caught!
        Task.Run(async () =>  // unnecessary async!?!   
        {
            throw new Exception("Exception in Task");
        }).Wait();
    }
    catch (Exception ex)
    {
        res = ex.Message;
    }

Why there is neccesary for async operator? All documentation i can find tells that delegate must not return Void and Task must be awaited for exception to propogate up to caller.

Added full code:

class Program
{
    static void Main(string[] args)
    {
        var p = new Program();
        p.Run();
    }

public void Run()
{
    string result;

    try
    {
        result = OnSomeEvent((s, ea) => RunSomeTask());
    }
    catch (Exception ex) // Try to catch unhandled exceptions here!
    {
        result = ex.Message;
    }

    Console.WriteLine(result);
    Console.ReadKey();
}

// Some other Framework bult-in event (can not change signature)
public string OnSomeEvent(EventHandler e)
{
    e.Invoke(null, new EventArgs());
    return "OK";
}

private async Task RunSomeTask()
{
    await Task.Run(async () => // do not need async here!!!
    //await Task.Run(() =>     // caller do not catches exceptions (but must)
    {
        throw new Exception("Exception in Task1");
    });
}
}

So the qestion is how to catche ex. without asyn keyword???


回答1:


Methods that return Task - such as Task.Run or async methods - will place any exceptions on that returned Task. It's up to you to observe that exception somehow. Normally this is done with await, like this:

await Task.Run(() => { throw ... });

In your case, the problem is in this line:

result = OnSomeEvent((s, ea) => RunSomeTask());

In this code, RunSomeTask is returning a Task, and that Task is never awaited. In order to observe the exception, you should await that task.




回答2:


When using async/await, exceptions are automatically unwrapped at the site of the await. When using a Task and .Wait(), any exception are wrapped when they come out of the Task, and thus getting information requires you to dig into the Task.Exception property, since they do not propagate up the call stack.

See https://dotnetfiddle.net/MmEXsT



来源:https://stackoverflow.com/questions/29849038/exception-handling-outside-of-task

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!