如何调试特定异步方法,在并行运行多个异步方法时?

3

看看这个示例代码:

class Program
{
    private static readonly Random Random = new Random();

    static async Task TaskBody()
    {
        var counter = Random.Next(100);

        while (true)
        {
            counter += Random.Next(100);
            await Task.Delay(5000);
            Console.WriteLine($"Counter = {counter}");
        }
    }

    static void Main(string[] args)
    {
        for (var i = 0; i < 10; i++)
        {
            var _ = TaskBody();
        }

        Console.ReadLine();
    }
}

假设有人需要调试这段代码(例如,while 循环体),那么显而易见的方法是在某个断点处停下来:

enter image description here

但是由于有10个异步方法并行运行,调试器会在每个方法处停止。

如果想要仅调试特定的方法怎么办?

最明显的方法是设置一些断点条件。
以下内容被视为条件:

  • ThreaId。不适用于异步方法,因为线程可以在await之后更改。
  • TaskId。可以(并且在此示例中将)为null
  • AsyncLocal<T>本地变量。不能在断点条件中使用AsyncLocal<T>.Value,因为它会导致本地方法调用,这是不允许的。
  • TaskBody签名更改。例如,在调度时传递一些“Id”(在示例中,最明显的方式是传递i)。这将起作用,但仅为了调试目的而需要不必要的更改。
  • 另一个本地变量(例如Guid)作为“方法Id”。这将起作用,并且看起来是最佳选项,但仍然是技巧。
我了解关于线程任务并行堆栈调试窗口的知识。
事实上,这个问题是在快速阅读this指南后提出的。
能否只使用VS2015的功能而不使用技巧和黑科技来实现这一点?

条件断点或添加变量并添加 if... - user6522773
“条件断点” - 是的,问题是要写什么作为条件。 - Dennis
ManagedThreadId:https://msdn.microsoft.com/zh-cn/library/system.threading.thread.managedthreadid(v=vs.110).aspx - user6522773
@x...:在异步方法执行期间,线程ID可以更改。异步方法的部分可以在不同的线程上执行。 - Dennis
1个回答

0

我认为最简单的方法是使用类似于Debug.WriteLine()的东西并输出您需要的任何内容,或者更好的方法是将某些值传递给Thread/Task(某种ID),然后只需设置条件断点,其中ID == Thread#

例如,您从1-10开始使用ID启动线程,并且您想要调试Thread#5

ID == 5的条件断点

我希望这个方法有效 :)

编辑:我认为后者是您在问题中提到的,但我认为这是最佳解决方案,而且ThreadID不应该有问题,除非您有很多线程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接