2015-09-01 88 views
2

我的代码看起来是这样的为什么async等待抛出NullReferenceException?

var userStartTask = LroMdmApiService.AddUser(user); 
// .... do some stuff 
await userStartTask; 

AddUser()抛出一个异常,它冒泡为NullReferenceException。它不等待等待。

但是,如果我构建这样的代码...

var result = await LroMdmApiService.AddUser(user); 

然后异常得到正确捕获。有人能告诉我这里发生了什么事吗?

下面是显示问题的完整代码。这种情况的最佳做法是什么?

class Program 
{ 
    private static void Main(string[] args) 
    { 
     CallAsync(); 
     Console.ReadKey(); 
    } 

    public static async void CallAsync() 
    { 
     var task = CallExceptionAsync(); 
     ThrowException("Outside"); 
     await task; 
    } 

    public static Task CallExceptionAsync() 
    { 
     return Task.Run(() => 
     { 
      ThrowException("Inside"); 
     }); 

    } 

    public static void ThrowException(string msg) 
    { 
     throw new Exception(msg); 
    }   
} 
+2

请提供一个简短但完整的例子来说明问题。只用这么多的代码很难帮助你。 –

+0

将userStartTask视为一个包含的方法,包含在您尝试分离的任务中。如果任务无法通过“var result”在方法内部返回,那么它必须返回到方法层。这意味着异常不包含在“var result”中,而是抛出在方法层。 –

+0

@JohnPeters,我在这里跟随微软的例子:https://msdn.microsoft.com/en-us/library/hh696703.aspx – Anish

回答

3

此代码

var result = await LroMdmApiService.AddUser(user); 

实际上等同于以下代码:

var task = LroMdmApiService.AddUser(user); 
var result = await task; 

当ADDUSER()抛出异常,它冒泡作为一个NullReferenceException。它不等待等待。

AddUser可能看起来像这样(其中_servicenull):

public static Task AddUser(User user) 
{ 
    return _service.AddUser(user); 
} 

这将导致NullReferenceException抛出直接,而不是放置在返回的任务。

如果你总是希望你的异常将被放置在返回的任务,然后让每个任务返回方法async

public static async Task AddUser(User user) 
{ 
    return await _service.AddUser(user); 
} 

但是,你应该考虑是否你真的想做到这一点。特别是NullReferenceException是一个代码错误;这不是你应该在生产中抓住或关心的例外。 To use Eric Lippert's term, it's a boneheaded exception

在我看来,无论在什么地方引发了异常 - 无论它们是直接抛出还是放置在任务上 - 都不重要,因为这些异常只针对开发人员,而不是运行时。

0

我找到了原因。两个例外被调用。在等待之前和任务内。第一个结束了线程并将执行返回给调用者。所以当第二个异常(来自任务)被引发时,它没有父线程。

var userStartTask = LroMdmApiService.AddUser(user); //1) An exception was being thrown inside AddUser() 
// .... do some stuff 2) And another exception was being thrown here 
await userStartTask; 

异常抛出内部杀死我的应用程序与NullReferenceException因为它调用的方法不再存在。

由于大家都在问例子,下面是一个简单的例子,它显示了同样的问题。

class Program 
{ 
    private static void Main(string[] args) 
    { 
     CallAsync(); 
     Console.ReadKey(); 
    } 

    public static async void CallAsync() 
    { 
     var task = CallExceptionAsync(); 
     ThrowException("Outside"); 
     await task; 
    } 

    public static Task CallExceptionAsync() 
    { 
     return Task.Run(() => 
     { 
      ThrowException("Inside"); 
     }); 

    } 

    public static void ThrowException(string msg) 
    { 
     throw new Exception(msg); 
    }   
} 
相关问题