Trace.WriteLine 线程安全吗?

问题描述 投票:0回答:3

我有一个多线程程序,我想使用 Trace.WriteLine,并将输出重定向到文本文件:

_LogTracer = new System.Diagnostics.TextWriterTraceListener(logPath);   
Trace.AutoFlush = true;
Trace.Listeners.Add(_LogTracer); 

这足以保证线程安全吗?如果两个线程尝试同时写入输出文件怎么办?

c# thread-safety trace
3个回答
3
投票

{wrt。整体线程安全}

当明确禁用

Trace.Listeners.Add
 时,相对于 Remove(或 
Trace.Write
),使用
WriteLine
(或 Trace.UseGlobalLock
不是
线程安全的。

Write
的线程安全(或缺乏)仅适用于单个跟踪侦听器类型(如前所述,TextWriterTraceListener 实现是线程安全的)或通过全局跟踪锁进行保护(有关讨论,请参阅
TraceListener.IsThreadSafe
)。

我有一些糟糕的旧代码,它们修改了侦听器集合,这可能会导致多线程环境中出现错误:

[System.InvalidOperationException]
Collection was modified; enumeration operation may not execute.
-------------------------------------------------- -- >
   at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
   at System.Diagnostics.TraceInternal.WriteLine(String message, String category)

文档说

Listeners
是线程安全的,这有点误导:
Listeners.GetEnumerator
确实 not 建立了暗示的锁定复制。线程安全锁只能通过几个单独的添加/删除方法获取。

要使

Trace.Write
相对于修改
Listeners
而言是线程安全的,需要使用
Trace.UseGlobalLock
,它将在枚举和写入所有侦听器时获取锁定。


3
投票

来自 Microsoft 文档

线程安全

该类型是线程安全的。


0
投票

这段代码证明了

TextWriterTraceListener
是线程安全的。在 .net6 中测试

Trace.Listeners.Clear();

Trace.Listeners.Add(new TextWriterTraceListener("C:\\temp\\TEMP-\\mylog.log"));

var rand = new Random();
var sw = Stopwatch.StartNew();

var t1 = Task.Run(() => Write(sw, "Thread#1", rand));
var t2 = Task.Run(() => Write(sw, "Thread#2", rand));
var t3 = Task.Run(() => Write(sw, "Thread#3", rand));

Task.WaitAll(t1, t2, t3);

Trace.Close();
//-----------
static void Write(Stopwatch sw, string threadName, Random rand)
{
    while(sw.Elapsed.TotalSeconds < 15)
    {
        int ms = rand.Next(10, 20);
        System.Threading.Thread.Sleep(ms);
        Trace.TraceInformation("Thread '{0}' @ {1}", threadName, ms);
    }

}

还有文件

测试代码信息:0:线程“Thread#2”@14
测试代码信息:0:线程“Thread#1”@18
测试代码信息:0:线程“Thread#2”@15
测试代码信息:0:线程“Thread#1”@18
测试代码信息:0:线程“Thread#1”@13
测试代码信息:0:线程“Thread#2”@12
测试代码信息:0:线程“Thread#1”@12
测试代码信息:0:线程“Thread#2”@14
测试代码信息:0:线程“Thread#1”@12
测试代码信息:0:线程“Thread#1”@10
测试代码信息:0:线程“Thread#2”@11
测试代码信息:0:线程“Thread#1”@16
测试代码信息:0:线程“Thread#2”@16
测试代码信息:0:线程“Thread#1”@12
测试代码信息:0:线程“Thread#2”@14
测试代码信息:0:线程“Thread#1”@14
测试代码信息:0:线程“Thread#2”@18
测试代码信息:0:线程“Thread#1”@12
测试代码信息:0:线程“Thread#2”@12
测试代码信息:0:线程“Thread#2”@16
测试代码信息:0:线程“Thread#3”@18
测试代码信息:0:线程“Thread#1”@18
测试代码信息:0:线程“Thread#1”@11
测试代码信息:0:线程“Thread#1”@13
测试代码信息:0:线程“Thread#3”@19
测试代码信息:0:线程“Thread#2”@19
测试代码信息:0:线程“Thread#1”@10
测试代码信息:0:线程“Thread#3”@14
测试代码信息:0:线程“Thread#1”@10

© www.soinside.com 2019 - 2024. All rights reserved.