VS Debugger Stops Working After Returning from "await" Call
Create a .NET Core Standard 2.1 CLI project in Visual Studio, then use this code, set a breakpoint at the "await" line, then run and step through the code. When the debugger is finished stepping through the "GetPackage" function, as soon as it returns from the function, the program immediately executes the rest of the code and completes without the expected behavior of the debugger continuing to the next "int g = 9;" line, stopping, and waiting.
Any idea why the ITask is breaking the VS debugger?
using MorseCode.ITask;
using System;
using System.Threading.Tasks;
namespace ConsoleApp1_AsyncBugTest_NETCore
{
class Program
{
static async Task Main(string[] args)
{
Test test = new Test();
int j = 0;
await test.GetPackage();
int g = 9;
Console.WriteLine("Hello World!");
}
public class PackageBase
{
}
public class NullPackage : PackageBase
{
}
public class Test
{
NullPackage nullPackage;
public async ITask<NullPackage> GetPackage()
{
if (nullPackage == null)
nullPackage = new NullPackage();
return await Task.FromResult(nullPackage).AsITask();
}
}
}
}
Edit/Update: If I remove the ITask and revert back to using a regular Task, the debugger acts as expected, so it's definitely a problem with ITask.
I have the same issue. For anyone looking for a workaround:
- This seems to primarily happen when nothing is awaited or when returning
Task.FromResult(...).AsITask(). When awaiting a task this seems to work as expected: e.g.await Task.Delay(...)evenawait (Task.Delay(...).AsITask())edit: while the debugger no longer detaches, it no longer continues with the next line, but seems to bubble up. - Since I was primarily interested in interface covariance one could also abstract most usage away, like this:
interface ICommand<out T> {
ITask<T> ExecuteAsync();
}
abstract class BaseCommand<T> : ICommand<T> {
abstract Task<T> ExecuteAsync();
[DebuggerStepThrough]
ITask<T> ICommand<T>.ExecuteAsync() => ExecuteAsync().AsITask();
}
As a side note: if this is all you need, you do not require an AsyncMethodBuilder, just a task/awaiter type (and not the complete task-like type setup). Thus this bug seems to be connected with AsyncMethodBuilder and not GetAwaiter, altough I was unable to correctly diagnose/fix this and gave up.