首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Parallel.ForEach Pretty日志记录不可能吗?

Parallel.ForEach Pretty日志记录不可能吗?
EN

Stack Overflow用户
提问于 2021-10-02 22:40:08
回答 4查看 110关注 0票数 2

我在想,在使用Parallel.ForEach时,不可能有一个漂亮的日志。除非有人能教我点小把戏?

代码语言:javascript
复制
namespace Parallel_ForEach_Logging
{
    class Program
    {
        private static uint _callCount = 0;

        static void Main(string[] args)
        {
            IEnumerable<int> data = Enumerable.Range(0, 2);

            Console.Out.WriteLine("***");

            ParallelOptions options = new();
            options.MaxDegreeOfParallelism = Environment.ProcessorCount;

            Parallel.ForEach(data, options, datum =>
            {
                PrintNum(datum, _callCount++);
            });

            Console.Out.Flush();
            Console.Out.WriteLine("***");
        }

        public static void PrintNum(int num, uint callCount)
        {
            Console.Out.WriteLine($">>> IN {callCount}");
            // Console.Out.WriteLine($"  {num}");
            Console.Out.WriteLine($"<<< OUT {callCount}");
            PrintString($"\"{num.ToString()}\"", callCount);
        }

        public static void PrintString(string str, uint callCount)
        {
            Console.Out.WriteLine($">>> IN {callCount}");
            // Console.Out.WriteLine($"  {str}");
            Console.Out.WriteLine($"<<< OUT {callCount}");
        }
    }
}

当我说“漂亮的日志”时,我会想到以下几点:

代码语言:javascript
复制
>>> IN: Method A
  >>> IN : Method 1 called.
  <<< OUT: Method 1 done.
  >>> IN : Method 2 called.
  <<< OUT: Method 2 done.
<<< OUT: Method A done in 32 milliseconds.
>>> IN: Method B
...

以下是我目前获得的示例日志:

代码语言:javascript
复制
>>> IN 1
>>> IN 0
<<< OUT 0
<<< OUT 1
>>> IN 0
<<< OUT 0
>>> IN 1
<<< OUT 1

请注意,在顶部有两个IN背靠背,然后两个OUT背靠背。

在代码中,_callCount是我试图确定用于缩进的调用深度,但我不知道如何实现这一点。即使我这样做了,我也不确定我能不能在每个日志条目中没有一百万个空格。

我知道,如果我把Parallel.ForEach从等式中去掉,我肯定可以让它工作。

如果这真的是不可能实现的,我也没问题。我只需要一个比我聪明得多的人来这么说。;)

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2021-10-03 06:26:56

使用StringBuilder作为缓冲区。将其作为参数添加到打印函数中,如下所示:

代码语言:javascript
复制
public static void PrintNum(StringBuilder builder, int num, uint callCount)
{
    builder.Append($">>> IN {callCount}\r\n");
    builder.Append($"<<< OUT {callCount}\r\n");
    PrintString(builder, $"\"{num.ToString()}\"", callCount);
}

public static void PrintString(StringBuilder builder, string str, uint callCount)
{
    builder.Append($">>> IN {callCount}\r\n");
    builder.Append($"<<< OUT {callCount}\r\n");
}

现在你可以这样做了:

代码语言:javascript
复制
Parallel.ForEach(data, options, datum =>
{
    var builder = new StringBuilder();
    PrintNum(builder, datum, _callCount++);
    Console.Out.WriteLine(builder.ToString());
});
票数 1
EN

Stack Overflow用户

发布于 2021-10-02 23:59:23

您可以将呼叫锁定到PrintString。请记住,这样做会使其他线程停止,直到当前线程释放锁为止。因此,在这种情况下,通过这样做,您的代码实际上是连续的,但线程打印的顺序实际上是随机的。

票数 1
EN

Stack Overflow用户

发布于 2021-10-03 00:23:04

除了锁定线程之外,我能想到的唯一其他方法是在元组或类中使用包含调用计数和方法名称的ConcurrentBag。然后,在ForEach完成之后,您可以使用调用计数和方法名对此集合进行排序,这样它就可以按顺序显示。

这可能是作弊,因为它不是实时的,但除此之外,我不知道你是如何做到这一点的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69420781

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档