admin管理员组文章数量:1026989
I have the following code in a WPF .NET 8 application.
When the exception is hit, the only callstack is:
WpfApp119.ViewModel.Compute() Line 23 C#
WpfApp119.ViewModel.LoadData.AnonymousMethod__0_0() Line 18 C#
System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread threadPoolThread, System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot, System.Threading.Thread threadPoolThread) Unknown
System.Threading.ThreadPoolWorkQueue.Dispatch() Unknown
System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart() Unknown
So you don't know whether it was called from MainWindow.Button_Click1
or MainWindow.Button_Click2
.
So if this code was in a real app, or in a test, how would you diagnose where the call originated from?
public class ViewModel
{
public async Task LoadData()
{
await Task.Run(() => Compute());
}
private void Compute()
{
throw new Exception("");
}
}
public partial class MainWindow : Window
{
private ViewModel _viewModel = new();
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click1(object sender, RoutedEventArgs e)
{
await _viewModel.LoadData();
}
private async void Button_Click2(object sender, RoutedEventArgs e)
{
await _viewModel.LoadData();
}
}
I have the following code in a WPF .NET 8 application.
When the exception is hit, the only callstack is:
WpfApp119.ViewModel.Compute() Line 23 C#
WpfApp119.ViewModel.LoadData.AnonymousMethod__0_0() Line 18 C#
System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread threadPoolThread, System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot, System.Threading.Thread threadPoolThread) Unknown
System.Threading.ThreadPoolWorkQueue.Dispatch() Unknown
System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart() Unknown
So you don't know whether it was called from MainWindow.Button_Click1
or MainWindow.Button_Click2
.
So if this code was in a real app, or in a test, how would you diagnose where the call originated from?
public class ViewModel
{
public async Task LoadData()
{
await Task.Run(() => Compute());
}
private void Compute()
{
throw new Exception("");
}
}
public partial class MainWindow : Window
{
private ViewModel _viewModel = new();
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click1(object sender, RoutedEventArgs e)
{
await _viewModel.LoadData();
}
private async void Button_Click2(object sender, RoutedEventArgs e)
{
await _viewModel.LoadData();
}
}
Share
Improve this question
edited Nov 16, 2024 at 22:10
Theodor Zoulias
44.6k7 gold badges108 silver badges145 bronze badges
asked Nov 16, 2024 at 12:29
creativergkcreativergk
655 bronze badges
9
|
Show 4 more comments
1 Answer
Reset to default 0What you show looks perfectly reasonable. This is because .NET asynchronous model is based on multiple threads. If you perform the test as you described and have an unhandled exception, you really cannot directly see what button initiated the problematic piece of code simply because the button handling code never calls it directly. Your await
call, strictly speaking, is not a call, the real underlying call was performed by some instance of System.Threading.PortableThreadPool.WorkerThread
.
The call stack (and, by the way, the exception stack created by all of your try
points as they are passed during runtime) belongs to one single thread, and is one of the most important parts of the thread identity — if two threads are different, they are executed on two different call stacks. And the thread showing your stack trace is not you UI thread.
Fet about async
for a second, but create a thread in your code during runtime and start it using System.Threading.Thread.Start
. Isn't it obvious that the code running by this newly created thread contains no information on how it was started? There is nothing on its call stack beyond the thread start method passed to the Thread
constructor. The same thing goes for your buttons.
And if the information on the button that originated your problematic piece of code is not known to some thread, is it even important? Anyway, if, for debugging purposes, you need to find out which button originated the asynchronous call, you can always run the debugging session where you click only one button and never click another one. :-)
I have the following code in a WPF .NET 8 application.
When the exception is hit, the only callstack is:
WpfApp119.ViewModel.Compute() Line 23 C#
WpfApp119.ViewModel.LoadData.AnonymousMethod__0_0() Line 18 C#
System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread threadPoolThread, System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot, System.Threading.Thread threadPoolThread) Unknown
System.Threading.ThreadPoolWorkQueue.Dispatch() Unknown
System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart() Unknown
So you don't know whether it was called from MainWindow.Button_Click1
or MainWindow.Button_Click2
.
So if this code was in a real app, or in a test, how would you diagnose where the call originated from?
public class ViewModel
{
public async Task LoadData()
{
await Task.Run(() => Compute());
}
private void Compute()
{
throw new Exception("");
}
}
public partial class MainWindow : Window
{
private ViewModel _viewModel = new();
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click1(object sender, RoutedEventArgs e)
{
await _viewModel.LoadData();
}
private async void Button_Click2(object sender, RoutedEventArgs e)
{
await _viewModel.LoadData();
}
}
I have the following code in a WPF .NET 8 application.
When the exception is hit, the only callstack is:
WpfApp119.ViewModel.Compute() Line 23 C#
WpfApp119.ViewModel.LoadData.AnonymousMethod__0_0() Line 18 C#
System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread threadPoolThread, System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot, System.Threading.Thread threadPoolThread) Unknown
System.Threading.ThreadPoolWorkQueue.Dispatch() Unknown
System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart() Unknown
So you don't know whether it was called from MainWindow.Button_Click1
or MainWindow.Button_Click2
.
So if this code was in a real app, or in a test, how would you diagnose where the call originated from?
public class ViewModel
{
public async Task LoadData()
{
await Task.Run(() => Compute());
}
private void Compute()
{
throw new Exception("");
}
}
public partial class MainWindow : Window
{
private ViewModel _viewModel = new();
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click1(object sender, RoutedEventArgs e)
{
await _viewModel.LoadData();
}
private async void Button_Click2(object sender, RoutedEventArgs e)
{
await _viewModel.LoadData();
}
}
Share
Improve this question
edited Nov 16, 2024 at 22:10
Theodor Zoulias
44.6k7 gold badges108 silver badges145 bronze badges
asked Nov 16, 2024 at 12:29
creativergkcreativergk
655 bronze badges
9
- 1 The event should be present in the stack: dotnetfiddle/kTIBFY – shingo Commented Nov 16, 2024 at 14:25
- 1 @TheodorZoulias .NET 8 – creativergk Commented Nov 16, 2024 at 14:27
- @shingo haven't you changed the code though? if I run this code in a normal WPF app, I get the stack I posted above. – creativergk Commented Nov 16, 2024 at 14:28
- How do you catch this stack in a normal WPF app? – shingo Commented Nov 16, 2024 at 14:41
-
Just a simple try/catch inside of
Compute()
and then log exception (with its stack) – creativergk Commented Nov 16, 2024 at 15:00
1 Answer
Reset to default 0What you show looks perfectly reasonable. This is because .NET asynchronous model is based on multiple threads. If you perform the test as you described and have an unhandled exception, you really cannot directly see what button initiated the problematic piece of code simply because the button handling code never calls it directly. Your await
call, strictly speaking, is not a call, the real underlying call was performed by some instance of System.Threading.PortableThreadPool.WorkerThread
.
The call stack (and, by the way, the exception stack created by all of your try
points as they are passed during runtime) belongs to one single thread, and is one of the most important parts of the thread identity — if two threads are different, they are executed on two different call stacks. And the thread showing your stack trace is not you UI thread.
Fet about async
for a second, but create a thread in your code during runtime and start it using System.Threading.Thread.Start
. Isn't it obvious that the code running by this newly created thread contains no information on how it was started? There is nothing on its call stack beyond the thread start method passed to the Thread
constructor. The same thing goes for your buttons.
And if the information on the button that originated your problematic piece of code is not known to some thread, is it even important? Anyway, if, for debugging purposes, you need to find out which button originated the asynchronous call, you can always run the debugging session where you click only one button and never click another one. :-)
本文标签: cCalling method missing in async stack traceStack Overflow
版权声明:本文标题:c# - Calling method missing in async stack trace - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745658384a2161735.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
Compute()
and then log exception (with its stack) – creativergk Commented Nov 16, 2024 at 15:00