В статье, которую вы нашли, хорошо объясняется, почему стеки вызовов не работают так, как думают многие из нас. Технически, стек вызовов сообщает нам, где код возвращается после текущего метода. Другими словами, стек вызовов «где код идет», а не «откуда пришел код».
Интересно, что в статье упоминается решение, но не излагает его , У меня есть сообщение в блоге, которое подробно объясняет CallContext
решение . По сути, вы используете контекст логического вызова для создания своего собственного «диагностического контекста».
Мне нравится решение CallContext
лучше, чем решение, представленное в статье, потому что оно работает, все формы async
код (включая код fork / join, такой как Task.WhenAll
).
Это лучшее решение, которое я знаю (кроме того, что вы делаете что-то действительно сложное, например, подключаетесь к API профилирования). Оговорки подхода CallContext
:
Код (зависит от неизменяемых коллекций Библиотека NuGet ):
public static class MyStack
{
private static readonly string name = Guid.NewGuid().ToString("N");
private static ImmutableStack CurrentContext
{
get
{
var ret = CallContext.LogicalGetData(name) as ImmutableStack;
return ret ?? ImmutableStack.Create();
}
set
{
CallContext.LogicalSetData(name, value);
}
}
public static IDisposable Push([CallerMemberName] string context = "")
{
CurrentContext = CurrentContext.Push(context);
return new PopWhenDisposed();
}
private static void Pop()
{
CurrentContext = CurrentContext.Pop();
}
private sealed class PopWhenDisposed : IDisposable
{
private bool disposed;
public void Dispose()
{
if (disposed)
return;
Pop();
disposed = true;
}
}
// Keep this in your watch window.
public static string CurrentStack
{
get
{
return string.Join(" ", CurrentContext.Reverse());
}
}
}
Использование:
static async Task SomeWorkAsync()
{
using (MyStack.Push()) // Pushes "SomeWorkAsync"
{
...
}
}
Обновление: я выпустил пакет NuGet (описанный в моем блоге) , который использует PostSharp для автоматического ввода тонов и всплывающих окон. Поэтому получить хороший след теперь будет намного проще.
>>> mydict = {'a':1,'b':3,'c':2}
>>> sorted(mydict, key=lambda key: mydict[key])
['a', 'c', 'b']
[v[0] for v in sorted(foo.items(), key=lambda(k,v): (v,k))]