尝试写入 TextWriter/StreamWriter 时出现 ArgumentOutOfRangeException
ArgumentOutOfRangeException when trying to write to TextWriter/StreamWriter
我在 TextWriter
实例上调用 Write
时遇到了这个奇怪的异常:
Unhandled exception. System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
at System.IO.FileStream.FlushWriteBuffer()
at System.IO.FileStream.WriteSpan(ReadOnlySpan`1 source)
at System.IO.FileStream.Write(Byte[] array, Int32 offset, Int32 count)
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.WriteLine(String value)
at Iot.Device.Common.SimpleFileLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter) in C:\Projects\iot\src\devices\Common\Iot\Device\Common\SimpleFileLogger.cs:line 49
// More irrelevant stuff here...
有问题的那一行就这样了(作者当然没有处理也没有关闭):
// _writer is an instance of StreamWriter
_writer.WriteLine($"{time.ToShortDateString()} {time.ToLongTimeString()} - {_category} - {logLevel} - {msg}");
根据文档,TextWriter.WriteLine
永远不会抛出 ArgumentOutOfRangeException,甚至查看 FlushWriteBuffer
方法的源代码也没有显示任何可能导致此问题的原因(我使用的是 .NET 5.0):
private void FlushWriteBuffer(bool calledFromFinalizer = false)
{
if (_writePos == 0) return;
Debug.Assert(_readPos == 0 && _readLength == 0, "FileStream: Read buffer must be empty in FlushWrite!");
if (_useAsyncIO)
{
// Irrelevant case
}
else
{
WriteCore(new ReadOnlySpan<byte>(GetBuffer(), 0, _writePos));
}
_writePos = 0;
}
为什么我会得到这个异常?它是在哪里创建的?
看来 StreamWriter
是 不是 线程安全的。我正在使用上面的日志记录任务从不同的线程记录到同一个文件中。
要解决此问题,请创建 StreamWriter
并对其进行同步包装:
_writer = TextWriter.Synchronized(new StreamWriter(fileName, true, Encoding.UTF8));
我在 TextWriter
实例上调用 Write
时遇到了这个奇怪的异常:
Unhandled exception. System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
at System.IO.FileStream.FlushWriteBuffer()
at System.IO.FileStream.WriteSpan(ReadOnlySpan`1 source)
at System.IO.FileStream.Write(Byte[] array, Int32 offset, Int32 count)
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.WriteLine(String value)
at Iot.Device.Common.SimpleFileLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter) in C:\Projects\iot\src\devices\Common\Iot\Device\Common\SimpleFileLogger.cs:line 49
// More irrelevant stuff here...
有问题的那一行就这样了(作者当然没有处理也没有关闭):
// _writer is an instance of StreamWriter
_writer.WriteLine($"{time.ToShortDateString()} {time.ToLongTimeString()} - {_category} - {logLevel} - {msg}");
根据文档,TextWriter.WriteLine
永远不会抛出 ArgumentOutOfRangeException,甚至查看 FlushWriteBuffer
方法的源代码也没有显示任何可能导致此问题的原因(我使用的是 .NET 5.0):
private void FlushWriteBuffer(bool calledFromFinalizer = false)
{
if (_writePos == 0) return;
Debug.Assert(_readPos == 0 && _readLength == 0, "FileStream: Read buffer must be empty in FlushWrite!");
if (_useAsyncIO)
{
// Irrelevant case
}
else
{
WriteCore(new ReadOnlySpan<byte>(GetBuffer(), 0, _writePos));
}
_writePos = 0;
}
为什么我会得到这个异常?它是在哪里创建的?
看来 StreamWriter
是 不是 线程安全的。我正在使用上面的日志记录任务从不同的线程记录到同一个文件中。
要解决此问题,请创建 StreamWriter
并对其进行同步包装:
_writer = TextWriter.Synchronized(new StreamWriter(fileName, true, Encoding.UTF8));