Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Extension method to add "logical" stack trace to async methods, with usage example. Copy/paste in Linqpad and add the following namespaces: - System.Runtime.CompilerServices - System.Threading.Tasks

View AsyncStackTrace.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
async void Main()
{
try
{
await FooAsync().AsyncTrace();
}
catch(Exception ex)
{
ex.FullTrace().Dump();
}
}
 
async Task FooAsync()
{
await Console.Out.WriteLineAsync("Entering FooAsync");
await BarAsync().AsyncTrace();
await Console.Out.WriteLineAsync("Leaving FooAsync");
}
 
async Task BarAsync()
{
await Console.Out.WriteLineAsync("Entering BarAsync");
string s = await BazAsync().AsyncTrace();
Console.WriteLine(s);
await Console.Out.WriteLineAsync("Leaving BarAsync");
}
 
 
async Task<string> BazAsync()
{
await Console.Out.WriteLineAsync("Entering BazAsync");
throw new Exception("Oops");
return "hello world";
await Console.Out.WriteLineAsync("Leaving BazAsync");
}
 
 
static class AsyncExceptionExtensions
{
public static async Task AsyncTrace(
this Task task,
[CallerMemberName] string callerMemberName = null,
[CallerFilePath] string callerFilePath = null,
[CallerLineNumber] int callerLineNumber = 0)
{
try
{
await task;
}
catch (Exception ex)
{
AddAsyncStackTrace(ex, callerMemberName, callerFilePath, callerLineNumber);
throw;
}
}
public static async Task<T> AsyncTrace<T>(
this Task<T> task,
[CallerMemberName] string callerMemberName = null,
[CallerFilePath] string callerFilePath = null,
[CallerLineNumber] int callerLineNumber = 0)
{
try
{
return await task;
}
catch (Exception ex)
{
AddAsyncStackTrace(ex, callerMemberName, callerFilePath, callerLineNumber);
throw;
}
}
private static void AddAsyncStackTrace(Exception ex, string callerMemberName, string callerFilePath, int callerLineNumber = 0)
{
var trace = ex.Data["_AsyncStackTrace"] as IList<string>;
if (trace == null)
trace = new List<string>();
trace.Add(string.Format("@{0}, in '{1}', line {2}", callerMemberName, callerFilePath, callerLineNumber));
ex.Data["_AsyncStackTrace"] = trace;
}
public static string AsyncTrace(this Exception ex)
{
var trace = ex.Data["_AsyncStackTrace"] as IList<string>;
if (trace == null)
return string.Empty;
return string.Join("\n", trace);
}
public static string FullTrace(this Exception ex)
{
var trace = ex.Data["_AsyncStackTrace"] as IList<string>;
if (trace == null)
return string.Empty;
return string.Format("{0}\n--- Async stack trace:\n\t", ex)
+ string.Join("\n\t", trace);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.