Можно ли получить эквивалентную трассировку стека, предоставляемую отладчиком Visual Studio 2019.
Например, если я устанавливаю точку останова в своем асинхронном коде внутри Visual Studio, я вижу следующую трассировку стека в «Вызове». Окно стека
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#
Если я позвоню new System.Diagnostics.StackTrace(1,true)
, я получу следующее
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
Что мне действительно нравится в отладчике визуальной студии, так это то, что он может выяснить, что происходит раньшемеханизм асинхронного состояния.
[Resuming Async Method]
[External Code]
[Async Call Stack]
Например, код перед «стеком асинхронных вызовов». Как отладчик Visual Studio получает этот стек вызовов и как я могу получить его в коде?
Я пробовал следующий пакет nuget, который немного очищает стек, но не помогает найти переход до нативного кодапереход.
https://github.com/benaadams/Ben.Demystifier