您要做的事並不容易。 Console.WriteLine()
et al are static
,因爲它們是共享的;任何調用這些方法的線程都會向標準輸出流寫入標準輸出流。
將輸出分割成單獨文件的最簡單方法是創建自己的TextWriter
,該文件包裝多個輸出文件,並將其設置爲標準輸出。然後,讓每個線程註冊您的TextWriter
,指定所需的輸出文件。每當調用進入編寫器時,它就會查看哪個線程進行了調用,然後寫入適當的文件。
這顯然需要一些工作才能得到正確的結果(因爲有許多競爭條件和資源共享問題是可能出現的問題),但可以讓您按照自己的意願去做。
編輯:下面是一個這樣的作者可能看起來像什麼樣子,以及它如何使用。 這個類是不完整的(例如,它目前僅支持WriteLine()
,對於string
s),並且也可能存在其他錯誤。
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();
}
這會打印出「你好」到控制檯,以及「你好從另一個線程」到文件「的test.txt」。
+1好的答案。但是它可能會(可能)更好地使用Thread dataslots。 – leppie
@leppie是的,我想管理的ID可以被重用,如果被終止的線程忘記調用'DeregisterThread()',這可能會導致意外的行爲。就像我說的,「這個代碼可能有bug」:) – dlev