I have an xUnit (2.1.0) test that always hangs/deadlocks. Here the code with the names of classes/methods changed for clarity and confidentiality:
[Fact]
public void DocumentModificationTest()
{
Exception ex = null;
using (TestDependency testDependency = new TestDependency())
{
TestDependencyDocument testDependencyDoc = testDependency.Document;
MockTestDependency fakeDependency = new MockTestDependency();
try
{
DoStuffToTheDocument(testDependencyDoc, "fileName.doc", fakeDependency);
}
catch (Exception e)
{
ex = e;
}
}
Assert.Null(ex);
}
If I set a breakpoint and step over until the assert I can see that ex is null and the test should pass and be done with, but it just hangs and I never see Test Successful on the runner.
Here's what DoStuffToTheDocument looks like:
public static void DoStuffToTheDocument(TestDependencyDocument document, string pFileName, MockTestDependency pContainer)
{
pContainer.CheckInTheDocFirst(async () =>
{
//check some stuff
//test returns early here
//check other stuff(test never gets here)
//await method (thus the async anonymous method)
});
}
And lastly here's what CheckInTheDocFirst looks like:
public void CheckInTheDocFirst(Action pConfirmAction)
{
pConfirmAction(); //since this is a method in a mock class only used for testing we just call the action
}
Any ideas whats happening here? Is there something with my async-await paradigm that is causing this test to hang?
It turns out that this is an issue caused by async void test method support in xUnit: https://github.com/xunit/xunit/issues/866#issuecomment-223477634
While you really should carry async all the way up, sometimes this isn't feasible because of interoperability concerns. You can't always change the signatures of everything you're working with.
One thing to note about your assert, however, is that it will always prove true even if there's an exception thrown in the async void method (the lambda, in this case). This is because exception handling is different for async void:
Async void methods have different error-handling semantics. When an exception is thrown out of an async Task or async Task method, that exception is captured and placed on the Task object. With async void methods, there is no Task object, so any exceptions thrown out of an async void method will be raised directly on the SynchronizationContext that was active when the async void method started. Figure 2 illustrates that exceptions thrown from async void methods can’t be caught naturally.
When you have an async function, you should really be async all the way down. Otherwise you run into issues with sync contexts being blocked which will result in lockups.
pContainer.CheckInTheDocFirst should be async and return a Task (since it's taking an async function that returns a Task object).
DoStuffToDocument should be an async function that returns a Task, since it calls an async function.
And finally, the test itself should also be an async method that returns a task.
If you run the async all the way up the stack, I think you'll find things just work.
Related
Consider the following highly simplified viewmodel for fetching and showing a list of projects:
public class ProjectListViewModel
{
private readonly IWebService _webService;
public ICommand RefreshCommand { get; }
// INotifyPropertyChanged implementation skipped for brevity
public ObservableCollection<Project> Projects { get; set; }
public ProjectListViewModel(IWebService serverApi)
{
_serverApi = serverApi;
// ICommand implemented by Xamarin.Forms
RefreshCommand = new Command(async () => await RefreshAsync());
}
private async Task RefreshAsync()
{
try
{
Projects = await _webService.GetProjectsAsync();
}
catch (TaskCanceledException)
{
// Empty (task only cancelled when we are navigating away from page)
}
}
}
Using NUnit and Moq, I'm trying test that when GetProjectsAsync throws a TaskCanceledException, the ViewModel will catch it. The closest I get is this:
[Test]
public void When_Refreshing_Catches_TaskCanceledException()
{
// Arrange
webService = new Mock<IServerApi>();
webService.Setup(mock => mock.GetProjectsAsync())
.ThrowsAsync(new TaskCanceledException());
vm = new ProjectListViewModel(webService.Object);
// Act and assert
Assert.That(() => vm.RefreshCommand.Execute(null), Throws.Nothing);
}
The test passes, but unfortunately it's faulty - it still passes if I throw e.g. Exception instead of TaskCanceledException. As far as I know, the reason is that the exception doesn't bubble up past the command lambda, async () => await RefreshAsync(), so no exception thrown by GetProjectsAsync will ever be detected by the test. (When running the actual app however, the TaskCanceledException will bubble up and crash the app if not caught. I suspect this is related to synchronization contexts, of which I have very limited understanding.)
It works if I debug the test - if I mock it to throw Exception, it will break on the line with the command/lambda definition, and if I throw TaskCanceledException, the test will pass.
Note that the results are the same if I use Throws instead of ThrowsAsync. And in case it's relevant, I'm using the test runner in ReSharper 2016.2.
Using nUnit, is it possible at all to unit test exceptions thrown when executing "async" commands like this? Is it possible without writing a custom Command implementation?
Your problem is here:
new Command(async () => await RefreshAsync())
This async lambda is converted to an async void method by the compiler.
In my article on async best practices, I explain why the exception cannot be caught like this. async methods cannot propagate their exceptions directly (since their stack can be gone by the time the exception happens). async Task methods solve this naturally by placing the exception on their returned task. async void methods are unnatural, and they have nowhere to place the exception, so they raise it directly on the SynchronizationContext that was current at the time the method started.
In your application, this is the UI context, so it's just like it was thrown directly in an event handler. In your unit test, there is no context, so it's thrown on a thread pool thread. I think NUnit's behavior in this situation is to catch the exception and dump it to the console.
Personally, I prefer using my own asynchronous-compatible ICommand such as AsyncCommand in my Mvvm.Async library (also see my article on asynchronous MVVM commands):
new AsyncCommand(_ => RefreshAsync())
which can then be naturally unit tested:
await vm.RefreshCommand.ExecuteAsync(null); // does not throw
Alternatively, you can provide your own synchronization context in the unit test (using, e.g., my AsyncContext):
// Arrange
webService = new Mock<IServerApi>();
webService.Setup(mock => mock.GetProjectsAsync())
.ThrowsAsync(new TaskCanceledException());
vm = new ProjectListViewModel(webService.Object);
// Act/Assert
AsyncContext.Run(() => vm.RefreshCommand.Execute(null));
In this case, if there was an exception, Run would propagate it.
Since async void (which is what the handler to your command is) is basically "fire and forget" and you can't await for it in the test I would suggest unit testing the RefreshAsync() method (you may want to make it internal or public), this can be easily done in NUnit:
if you are asserting exceptions being thrown:
[Test]
public async Task Test_Exception_RefreshAsync(){
try
{
await vm.RefreshAsync();
Assert.Fail("No exception was thrown");
}
catch (NotImplementedException e)
{
// Pass
}
}
or simply
[Test]
public async Task Test_RefreshAsync(){
var vm = new ProjectListViewModel(...);
await vm.RefreshAsync();
//Assertions here
}
or as other answer state you can create your own AsyncCommand that you can await on.
Before/without Task<>s, I'm using a wrapper object like the below to encapsulate the result of an I/O operation that could fail, without propagating exceptions up the call stack:
public class FetchResult<T>
{
public readonly bool Success;
public readonly T Item;
public FetchResult(bool success, T item)
{
this.Success = success;
this.Item = item;
}
}
I'd use it like this:
var userResult = Get("robert.paulson#fightclub.com");
if(!userResult.Success)
// abort, or something
...
public FetchResult<User> Get(string email)
{
try
{
// go to database here, and get the User
return new FetchResult(true, new User());
}
catch
{
// log exception
return new FetchResult(false, null);
}
}
This works great for me as a model, as it allows me to effectively manage exceptions without using try/catch as program control flow and gives me easy and fine-grained graceful service degredation.
However, with the advent of Task<>, I could very easily end up with:
public Task<FetchResult<User>> GetAsync(string email)
which seems to be getting out of hand.
Seeing as I'm migrating to async everywhere anyway, I'm contemplating just doing:
public Task<User> GetAsync(string email)
which id have expected to allow me to do something like:
var userTask = GetAsync("robert.paulson#fightclub.com");
await userTask;
if(userTask.IsFaulted) // (*) - see below
// abort, or something
However if my GetAsync method returns:
return Task<User>.FromException(new Exception());
what is actually returned after the await (where the (*) comment is) seems to be a Completed Task, whos result is a Task<User> which is faulted.
Why am I getting a nested task in this case, and is there some syntactic sugar I'm missing to make this whole affair tidier?
There are two methods in Task library FromException() and FromException<TResult>() both are available via Task and Task<TResult>.
public static Task FromException(Exception exception)
{
return FromException<VoidTaskResult>(exception);
}
public static Task<TResult> FromException<TResult>(Exception exception)
{
...
...
}
If you call Task<TResult>.FromException() or Task.FromException() there's no different in these two calls.
Your method signature is: public Task<User> GetAsync(string email)
Now if you try to use Task<User>.FromException(new Exception()) this will return Task<VoidTaskResult> and which is ofcourse is not of type Task<User>. Which means you might be getting compiler error.
This compile time error would be gone if you use Task<User>.FromException<User>(new Exception()); or Task.FromException<User>(new Exception());
You're getting Task<Task<VoidTaskResult>> as specified in comments means there's something more in your method code which is not mentioned in your sample code.
For more internal details about Task methods in .Net source code see here
Update:
After looking at your code found couple of issues.
i) Return type as Task is avoiding the compilation error that I mentioned earlier in my answer.
ii) You're returning a Task with in a Async method without awaiting means the complete task object will be wrapped in Another Task type.
See below example that I tweaked to to show the problem. See even the return type is changed from Task of type Object to Program there's still no error. This is Because of Object which is base of any custom type in C#. So doing below is allowed:
static async Task<object> GetAsync()
{
try
{
throw new Exception();
}
catch (Exception e)
{
return Task.FromException<Program>(e);
}
}
Now change the return type of method to Task<Program> you'll get an error or more of warning.
Now the correct version to fix the problem would be to await the Task so that only Program type remain as result which will be automatically returned as Task<Program>.
Correct version:
static async Task<Program> GetAsync()
{
try
{
throw new Exception();
}
catch (Exception e)
{
return await Task.FromException<Program>(e);
}
}
Now you won't see any Nested tasks anymore. This is internals of how await works. If you really want know why it happens like this then try to analyze the IL generated of all the above 3 versions of the program using IL spy and you'll get the idea. Cheers!!!
Kind of unusual, but you can explore the fact that the Task.WhenAny method does not throw exception (see Is there a way to Wait for a TPL Task without in throwing an exception?) like this
var userTask = GetAsync("robert.paulson#fightclub.com");
await Task.WaitAny(userTask);
if(userTask.IsFaulted) // (*) - see below
// abort, or something
Task.IsFaulted means that the Task completed due to an unhandled exception. So I don't think you could set it in a different way than to let the exception go uncaught.
public async Task<User> GetAsync(string email)
{
// go to database here, and get the User
return new User();
}
Or catch, log, and rethrow:
public async Task<User> GetAsync(string email)
{
try
{
// go to database here, and get the User
return new User();
}
catch
{
// log exception
throw;
}
}
I believe you are saying that your GetAsync is returning a nested task because you have something like this:
public async Task GetAsync(string email)
{
// .... somewhere in the code
return Task.FromException(new Exception());
}
But when you declare a method using the async keyword, C# magic takes care of wrapping its contents inside a Task. So in this case you actually end up having a task which returns another task - Task<Task<T>>. It would return Task<T> if you removed the async keyword but then obviously you end up with a standard synchronous method.
I'm trying to troubleshoot an issue where we believe an Async call may not execute in some instances.
Would doWork() complete executing even after the controller has returned and no call to EndInoke()?
Is there another case where this would not execute, like an exception throw in doWork()?
delegate void TestDelegate();
void doWork()
{
Thread.Sleep(5000);
}
public ActionResult Test()
{
var myAsyncCall = new TestDelegate(doWork);
myAsyncCall.BeginInvoke();
return View();
}
In general, you need to call EndInvoke on the delegate. This will allow you to determine why things are not working (like an exception being raised within doWork, which would explain the described issue).
For details, see Calling Synchronous Methods Asynchronously on MSDN.
That being said, I would recommend reworking this to use the the TPL instead of delegate.BeginInvoke, as it makes some of the checking simpler overall. You could write the above as:
public ActionResult Test()
{
// Start the async work, and attach a continuation which happens if exceptions occur
Task.Run(() => doWork())
.ContinueWith(t =>
{
var ex = t.Exception.InnerException;
LogException(ex);
}, TaskContinuationOptions.OnlyOnFaulted);
return View();
}
I have a class with an async method:
public static async Task GetData() { ... }
In the app framework I am using I need to start that process and forget about it when the app starts:
protected override void OnStart()
{
await MyService.GetData();
}
I can't make OnStart async. How do I start it in a background task and forget about it?
I can't make OnStart Async. How do I start it in a background task and
forget about it?
Why not? Nothing prevents you from making it async. The async modifier doesn't affect the CLR method signature, i.e., you can override a void method and make it async:
abstract class AppBase
{
protected abstract void OnStart();
}
class App: AppBase
{
public static async Task GetData() { await Task.Delay(1); }
protected override async void OnStart()
{
await GetData();
}
}
This way, at least you'll see an exception if GetData throws, unlike what the other answer suggests.
Make sure you understand how async void methods and Task error handling work in general, this material may be helpful.
Some other problems with Task.Run( () => MyService.GetData() ):
as GetData is already asynchronous, there's very little sense in wrapping it with Task.Run. It's usually only done in a client-side UI app and only if GetData has a long-running synchronous part (before it hits its 1st await). Otherwise, you might as well just call GetData() without Task.Run and without await (which also would be a bad idea: in either case, you'd be doing a fire-and-forget call without observing possible exceptions).
Task.Run will start GetData on a random pool thread without synchronization content, which may be a problem for either a UI app or an ASP.NET app.
If you want to fire this async operation and forget about it all you need to do is invoke the method without awaiting the returned task:
protected override void OnStart()
{
MyService.GetDataAsync();
}
However, since you're not observing the task you would never know if it completed successfully.
You should either keep a reference to the task and await it in a later time:
public Task _dataTask;
protected override void OnStart()
{
_dataTask = MyService.GetDataAsync();
}
public Task AwaitInitializationAsync()
{
return _dataTask;
}
Or add a continuation handling any exceptions:
protected override void OnStart()
{
MyService.GetDataAsync().ContinueWith(t =>
{
try
{
t.Wait();
}
catch (Exception e)
{
// handle exceptions
}
});
}
You shouldn't use Task.Run as Noseratio explained, however using async void is much worse since an exception in an async void method (which isn't a UI event handler) would tear down the entire process*.
You can try to make the method async void while making sure there won't be any exceptions thrown inside it with a try-catch block:
protected override async void OnStart()
{
try
{
await GetData();
}
catch (Exception e)
{
// handle e.
}
}
But I would still recommend against it since even the chance of a complete crash is dangerous.
*You can get around that by registering an even handler for AppDomain.CurrentDomain.UnhandledException but this should be a last resort, not a best practice
I'm currently trying to write async code and I have the feeling that my code is not too correct at all.
I have the following method:
public void Commit()
{
_context.SaveChangesToDatabase();
}
Don't judge the code here as this are only samples. Also, don't say that if I'm using Entity Framework, that they come packaged with Async methods already. I just want to understand the async concept here.
Let's say that the method SaveChangesToDatabase does takes seconds to complete.
Now, I don't want to wait for it so I create an async method:
public async Task CommitAsync()
{
await Task.Run(() => Commit());
}
Does this mean that if I have a method:
public void Method()
{
// Operation One:
CommitAsync();
// Operation Two.
}
Does this mean that my code on Operation two will be executed before CommitAsync() is even completed?
If not, please guide me in the right direction.
Update
Based on the remarks here that I'm ignoring my async method results, is this implementation better?
public Task<TaskResult> CommitAsync()
{
var task = new Task<TaskResult>(() =>
{
try { Commit(); }
catch (Exception ex)
{
return new TaskResult
{
Result = TaskExceutionResult.Failed,
Message = ex.Message
};
}
return new TaskResult { Result = TaskExceutionResult.Succeeded };
});
task.Start();
return task;
}
This does mean that I need to put the async modifier on the method that call this code so that I can await this which means continue with the current execution and return when this method has been completed.
Fire but don't forget
CommitAsync() returns a Task, but Method ignores the return value of CommitAsync completely -- so yes, the code will not wait but simply go on with what's after that. This is bad, because, if Commit() throws an exception, you will never see it. Ideally, every task should be waited on somewhere by someone, so you can at least see if it fails.
Let's say that you have no async alternative to SaveChangesToDatabase, but you'd like to use it in an async context anyway. You can use Task.Run to create a "fake-asynchronous" method, but this is not recommended (see below):
public Task CommitAsync() {
return Task.Run(() => Commit());
}
And then, assuming Method is doing something interesting with async (which the below code does not do since it's the only asynchronous operation in there):
public async Task MethodAsync() {
// Operation One:
await CommitAsync();
// Operation Two.
}
Assuming you do not want to wait, but you do want to do something if the task failed, you can use a separate method:
public void Method() {
// Operation One:
var _ = TryCommitAsync();
// Operation Two.
}
private async Task TryCommitAsync()
{
try
{
await CommitAsync();
}
catch (Exception ex)
{
Console.WriteLine(
"Committing failed in the background: {0}",
ex.Message
);
}
}
Getting back results
Let's suppose .Commit() does return something (like the number of records affected); a similar "fake-asynchronous" wrapper (again, not recommended - see below) would look like this:
public Task<int> CommitAsync() {
return Task.Run(() => Commit());
}
If you want this result, you can await the task immediately:
public async Task MethodAsync() {
// Operation One:
int recordsAffected = await CommitAsync();
// Operation Two.
}
Or, if you don't need it immediately, use await when you do:
public async Task MethodAsync() {
// Operation One:
Task<int> commit = CommitAsync();
// Operation Two.
// At this point I'd really like to know how many records were committed.
int recordsAffected = await commit;
}
Async: don't fake it
In general, you don't want to write wrappers like CommitAsync() because they mislead callers into thinking code will be asynchronous when it isn't really, which brings few benefits other than not blocking (which is still useful in UI code, but not as good as true asynchronous code which doesn't need to use worker threads for everything). In other words, you should use Task.Run in the invocation of a method, not as the implementation of a method.
So don't, as a habit, write wrappers like CommitAsync for every synchronous method you have -- instead you want to make a true CommitAsync that uses the async support of the underlying libraries/frameworks (SqlCommand.ExecuteReaderAsync(), etcetera.)
If you have no choice and must use Task.Run, then the appropriate usage would look more like:
// This method is in the UI layer.
public async Task MethodAsync() {
// Operation One:
// Commit() is a method in the DA layer.
await Task.Run(() => Commit());
// Operation Two.
}
Here
http://channel9.msdn.com/events/TechEd/NorthAmerica/2013/DEV-B318#fbid=
is a good explanation on how to work with async, and why you should avoid "async over sync", which is what you are doing now with
public Task CommitAsync() {
return Task.Run(() => Commit());
}
There are some scenarios where you can benefit from it, but if you are going to provide this as part of a library is NOT a good idea to make this.
If this code is ONLY and ONLY going to be used by your app, and you are sure what you are doing and dont have a wawy to call async methods inside your async method, just do it