在处理排队任务的工作线程中欺骗调用堆栈
Spoofing the call stack inside a worker thread that processes queued tasks
假设我有一个工作线程,其输入 Queue<Task>
在一个连续的 while
循环中处理。每当外部代码将新的 Task
存入队列时,工作人员就会醒来并等待任务实例。但是,如果出现异常,我想记录详细信息,包括完整的调用堆栈,以便确定应归咎于哪个代码路径。
不幸的是,异常的调用堆栈植根于工作线程内。这是可以理解的——它是执行任务的最根代码。
问题是:我可以假设将异常的调用堆栈与首先将任务放入工作线程队列的调用堆栈合并吗?
我知道我可以手动完成,只需记下通过 Environment.StackTrace
存放的调用堆栈并将其与工作程序中的异常一起记录下来。但这仍然是我必须跟踪的两个独立堆栈。
是否有更聪明的方法来欺骗异常自身的调用堆栈,使其看起来好像是连续的?因为它有点是 - 在任务入队和出队时的点之间只有轻微的延迟。
编辑:我基本上是在寻找一种方法来完成 C# 的 async
对调用堆栈所做的事情(即将它们合并到发生的所有线程跃点上) ,仅在我控制的常规线程内。
I know I can do it manually, by simply making note of the depositing call stack
这可能是更清洁的解决方案。
Is there a more clever way to spoof the exception's own call stack to look as if it was continuous?
是的,有一个 "clever" 解决方案 - 和大多数 "clever" 解决方案一样,YMMV。
首先,快速说明一下术语:what you want isn't a call stack (where the code is returning to); its a causality chain (how the code got here)。
您可以使用 AsyncLocal<T>
/ LogicalCallContext
自己跟踪因果链。一个容易被忽视的问题是 the data stored in the logical call context must be immutable。这种方法的一个更严重(谢天谢地,更罕见)的问题是,如果你有无限 "recursive" 个异步调用,这通常工作正常,但如果你在每次调用时增加因果链,你最终会得到无限的内存用法。
完成此设置后,您可以使用 Fody / PostSharp 等自动将因果链跟踪注入您的方法。
我有一个 AsyncDiagnostics library,它使用 LogicalCallContext
和 PostSharp
自动神奇地确定您的因果关系链。我会先试试。
假设我有一个工作线程,其输入 Queue<Task>
在一个连续的 while
循环中处理。每当外部代码将新的 Task
存入队列时,工作人员就会醒来并等待任务实例。但是,如果出现异常,我想记录详细信息,包括完整的调用堆栈,以便确定应归咎于哪个代码路径。
不幸的是,异常的调用堆栈植根于工作线程内。这是可以理解的——它是执行任务的最根代码。
问题是:我可以假设将异常的调用堆栈与首先将任务放入工作线程队列的调用堆栈合并吗?
我知道我可以手动完成,只需记下通过 Environment.StackTrace
存放的调用堆栈并将其与工作程序中的异常一起记录下来。但这仍然是我必须跟踪的两个独立堆栈。
是否有更聪明的方法来欺骗异常自身的调用堆栈,使其看起来好像是连续的?因为它有点是 - 在任务入队和出队时的点之间只有轻微的延迟。
编辑:我基本上是在寻找一种方法来完成 C# 的 async
对调用堆栈所做的事情(即将它们合并到发生的所有线程跃点上) ,仅在我控制的常规线程内。
I know I can do it manually, by simply making note of the depositing call stack
这可能是更清洁的解决方案。
Is there a more clever way to spoof the exception's own call stack to look as if it was continuous?
是的,有一个 "clever" 解决方案 - 和大多数 "clever" 解决方案一样,YMMV。
首先,快速说明一下术语:what you want isn't a call stack (where the code is returning to); its a causality chain (how the code got here)。
您可以使用 AsyncLocal<T>
/ LogicalCallContext
自己跟踪因果链。一个容易被忽视的问题是 the data stored in the logical call context must be immutable。这种方法的一个更严重(谢天谢地,更罕见)的问题是,如果你有无限 "recursive" 个异步调用,这通常工作正常,但如果你在每次调用时增加因果链,你最终会得到无限的内存用法。
完成此设置后,您可以使用 Fody / PostSharp 等自动将因果链跟踪注入您的方法。
我有一个 AsyncDiagnostics library,它使用 LogicalCallContext
和 PostSharp
自动神奇地确定您的因果关系链。我会先试试。