两个线程 - 两个用于 Console.out 的流

本文关键字:两个 out 的流 Console 线程 用于 | 更新日期: 2023-09-27 18:35:51

all

我有一个库,不是我的,所以它不能被修改。这个库有两个方法,我们称它们为 Method_1() 和 Method_2()。在这些方法中称为 Console.WriteLine("...")

我有一堂课

public class CustomBackgroundWorker: BackgroundWorker
{
         private readonly StringBuilder logBuilder;
         public CustomBackgroundWorker ()
         {
             logBuilder = new StringBuilder ();
             TextWriter outStream = new StringWriter (logBuilder);
             Console.SetOut (outStream);
         }
         public string GetLogs ()
         {
             return logBuilder.ToString ();
         }
}

它创建此类的两个实例。库中的每个实例执行方法。但是输出只保存在一个流中,因为 SetOut() 方法全局工作。是否可以将不同线程的输出重定向到单独的流?

感谢

两个线程 - 两个用于 Console.out 的流

你想做的事情并不容易做到。 Console.WriteLine()等人之所以static,是因为它们是共享的;调用这些方法的任何线程都将写入标准输出流。

将输出拆分为单独文件的最干净方法是创建自己的包装多个输出文件的TextWriter,并将其设置为标准输出。然后,让每个线程向TextWriter注册自身,指定所需的输出文件。每当调用编写器时,它都会查看哪个线程进行了调用,然后写入相应的文件。

这显然需要一些工作才能正确(因为可能会出现许多竞争条件和资源共享问题),但可以让您做您想做的事。

编辑:这是这样一个作家可能看起来像什么样子的示例,以及如何使用它。这个类是不完整的(例如,它目前只支持stringWriteLine()),并且可能还存在其他错误。

public class ThreadAwareStreamWriter : TextWriter
{
    private ConcurrentDictionary<int, TextWriter> threadWriterMap;
    private TextWriter defaultWriter;
    public ThreadAwareStreamWriter()
    {
        this.threadWriterMap = new ConcurrentDictionary<int, TextWriter>();
        this.defaultWriter = Console.Out;
    }
    public TextWriter RegisterThreadWriter(TextWriter threadWriter)
    {
        int threadId = Thread.CurrentThread.ManagedThreadId;
        TextWriter oldWriter;
        this.threadWriterMap.TryGetValue(threadId, out oldWriter);
        this.threadWriterMap[threadId] = threadWriter;
        return oldWriter;
    }
    public void DeregisterThread()
    {
        TextWriter threadWriter;
        if (this.threadWriterMap.TryRemove(Thread.CurrentThread.ManagedThreadId, out threadWriter))
        {
            threadWriter.Close();
        }
    }
    public override Encoding Encoding
    {
        get 
        {
            TextWriter threadWriter;
            if (this.threadWriterMap.TryGetValue(Thread.CurrentThread.ManagedThreadId, out threadWriter))
            {
                return threadWriter.Encoding;
            }
            return this.defaultWriter.Encoding;
        }
    }
    public override void WriteLine(string value)
    {
        TextWriter threadWriter;
        if (this.threadWriterMap.TryGetValue(Thread.CurrentThread.ManagedThreadId, out threadWriter))
        {
            threadWriter.WriteLine(value);
            return;
        }
        if (this.defaultWriter != null)
        {
            this.defaultWriter.WriteLine(value);
        }
    }
}

示例程序:

public static void Main(string[] args)
{
    ThreadAwareStreamWriter writer = new ThreadAwareStreamWriter();
    Console.SetOut(writer);
    Thread t = new Thread(o =>
    {
        ThreadAwareStreamWriter tWriter = (ThreadAwareStreamWriter)o;
        tWriter.RegisterThreadWriter(new StreamWriter(File.Open("test.txt", FileMode.Create, FileAccess.ReadWrite)));
        Console.WriteLine("Hello from another thread");
        tWriter.DeregisterThread();
    });
    t.Start(writer);
    Console.WriteLine("Hello");
    Console.ReadLine();
}
这将打印出"Hello"到

控制台,并将"来自另一个线程的 Hello"打印到文件"test.txt"。