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. :-)
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745658386a4638681.html
Compute()
and then log exception (with its stack) – creativergk Commented Nov 16, 2024 at 15:00