My code looks something like this
var userStartTask = LroMdmApiService.AddUser(user);
// .... do some stuff
await userStartTask;
When AddUser()
throws an exception, it bubbles up as a NullReferenceException
. It doesn't wait for await.
But if I structure the code like this...
var result = await LroMdmApiService.AddUser(user);
Then exceptions get caught properly. Can someone tell me what's going on here?
Here is complete code that shows the issue. What is the best practice for such a scenario?
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);
}
}
This error is caused when an object is trying to be used by a script but does not refer to an instance of an object. To fix this example we can acquire a reference to an instance of the script using GameObject.
The Null Reference Exception is not a major error, but one of the common ones and one of the basic and simple way to avoid the Null Reference Exception is to check the variable or property before moving ahead and accessing it. And a very basic way to do this is to check the variable within an if statement.
Solutions to fix the NullReferenceException To prevent the NullReferenceException exception, check whether the reference type parameters are null or not before accessing them. In the above example, if(cities == null) checks whether the cities object is null or not.
A NullReferenceException exception is thrown when you try to access a member on a type whose value is null . A NullReferenceException exception typically reflects developer error and is thrown in the following scenarios: You've forgotten to instantiate a reference type.
This code
var result = await LroMdmApiService.AddUser(user);
is practically identical to this code:
var task = LroMdmApiService.AddUser(user);
var result = await task;
When AddUser() throws an exception, it bubbles up as a NullReferenceException. It doesn't wait for await.
AddUser
probably looks like this (where _service
is null
):
public static Task AddUser(User user)
{
return _service.AddUser(user);
}
This will cause a NullReferenceException
to be thrown directly, not placed on the returned task.
If you always want your exceptions to be placed on the returned tasks, then make every task-returning method async
:
public static async Task AddUser(User user)
{
return await _service.AddUser(user);
}
However, you should consider whether you really want to do that. NullReferenceException
in particular is a code bug; it's not an exception you should ever catch or care about in production. To use Eric Lippert's term, it's a boneheaded exception.
In my opinion, it doesn't matter where boneheaded exceptions are thrown - whether they're thrown directly or placed on a task - because these exceptions are only for the developer, not runtime.
I found the cause. Two exceptions were getting called. Before await and inside the task. The first ended the thread and returned execution back to the caller. So when the 2nd exception (from the task) was raised, it had no parent thread.
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;
Exception thrown inside killed my app with the NullReferenceException bec/ the method it was called from no longer existed.
Since everybody is asking for examples, here is a simple example which shows the same issue.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With