Get stack trace of C# async calls using the API that the visual studio debugger uses

痴心易碎 提交于 2020-01-14 03:28:31

问题


Is it possible to get an equivalent stack trace that is provided by the visual studio 2019 debugger.

Eg if I breakpoint in my async code inside of visual studio I see the following stack trace within the "Call Stack" window

    company.Common.dll!company.Common.Api.ResourcesDatabase.Lock() Line 58  C#
    company.Common.dll!company.Common.Api.ResourcesDatabase.ResourcesDatabase(bool openAndCreateDB) Line 29 C#
    company.Api.dll!company.Api.GlobalsDownloader.DownloadNewGlobals_UnderLock(System.Func<company.Common.Api.DTO.GlobalsType, System.Threading.Tasks.Task> reloadGlobals, company.Common.Api.DTO.GlobalsType globalsType) Line 124 C#
    [Resuming Async Method] 
    [External Code] 
    [Async Call Stack]  
    [Async] company.Api.dll!company.Api.ApiService.VerifyLogin_UnderLock(bool skipInitTasks, System.Threading.CancellationToken ct) Line 1147   C#
    [Async] company.Api.dll!company.Api.ApiService.VerifyLogin(System.Threading.CancellationToken ct) Line 955  C#
    [Async] company.Api.dll!company.Api.ApiService.Init(System.Action initComplete, bool dontCheckForUpdates) Line 250  C#
    [Async] company.Editor.exe!company.Editor.ViewModel.MainViewModel.Init() Line 524   C#
    [Async] company.Editor.exe!company.Editor.ViewModel.MainViewModel.InitViewModel.AnonymousMethod__31_0() Line 331    C#

If I call new System.Diagnostics.StackTrace(1,true) I get the following

   at company.Common.Api.ResourcesDatabase.Lock()
   at company.Common.Api.ResourcesDatabase..ctor(Boolean openAndCreateDB)
   at company.Api.GlobalsDownloader.<DownloadNewGlobals_UnderLock>d__6.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.InvokeMoveNext(Object stateMachine)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c__DisplayClass4_0.<OutputAsyncCausalityEvents>b__0()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke()
   at System.Runtime.CompilerServices.TaskAwaiter.<>c__DisplayClass11_0.<OutputWaitEtwEvents>b__0()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke()
   at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action action, Boolean allowInlining, Task& currentTask)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task.FinishStageThree()
   ... 3 more layers of async
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task.FinishStageThree()
   at System.Threading.Tasks.Task`1.TrySetResult(TResult result)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.CompleteFromAsyncResult(IAsyncResult asyncResult)
   at System.IO.Compression.DeflateStreamAsyncResult.Complete(Object result)
   at System.IO.Compression.DeflateStream.ReadCallback(IAsyncResult baseStreamResult)
   at System.IO.Stream.ReadWriteTask.InvokeAsyncCallback(Object completedTask)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.IO.Stream.ReadWriteTask.System.Threading.Tasks.ITaskCompletionAction.Invoke(Task completingTask)
   at System.Threading.Tasks.Task.FinishContinuations()
   at System.Threading.Tasks.Task.FinishStageThree()
   at System.Threading.Tasks.Task.FinishStageTwo()
   at System.Threading.Tasks.Task.Finish(Boolean bUserDelegateExecuted)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
   at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
   at System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()    6.67s       

The bit that I really like about the visual studio debugger is it can figure out what occurs before the async state engine.

[Resuming Async Method] 
[External Code] 
[Async Call Stack]  

Eg the code before the "Async Call Stack". How does the visual studio debugger get this call stack and how can I get this in code?

I have tried the following nuget package which cleans up the stack slightly but doesn't help find the jump before the native code transition.

https://github.com/benaadams/Ben.Demystifier

来源:https://stackoverflow.com/questions/58620205/get-stack-trace-of-c-sharp-async-calls-using-the-api-that-the-visual-studio-debu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!