Two thread - two streams for Console.out

c#

Solution

What you're looking to do isn't easy to do. `Console.WriteLine()` et al are `static` because they are shared; any thread that calls those methods will write to the standard output stream.

The cleanest way to split the output into separate files would be to create your own `TextWriter` that wraps multiple output files, and set that as the standard output. Then, have each thread register itself with your `TextWriter`, specifying the desired output file. Whenever a call comes in to the writer, it looks at which thread made the call, and then writes to the appropriate file.

This obviously requires some work to get right (since there are numerous race conditions and resource sharing issues a whatnot that could arise) but would allow you to do what you want.

Edit: Here's a sample of what such a writer might look like, as well as how it might be used. This class is incomplete (e.g. it currently only supports `WriteLine()` for `string`s), and there are likely other bugs present as well.

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);
        }
    }
}

A sample program:

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();
}

This will print out "Hello" to the console, and "Hello from another thread" to the file "test.txt".

Problem

all I've a library, not my, so that then it can't be modified. This library has two methods, let's call them Method_1() and Method_2(). In these methods is called Console.WriteLine("...") I've a class ``` 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 (); } } ``` It creates two instance of this class. Each instance execute method from the library. But output save only in one stream, because SetOut() method work globally. Is it possible to redirect output from different thread to separate streams? Thx

Original source