从 .net core 2.1 与 .net core 3.0 调用时的 StreamWriter 类行为
Posted
技术标签:
【中文标题】从 .net core 2.1 与 .net core 3.0 调用时的 StreamWriter 类行为【英文标题】:StreamWriter class behavior when call from .net core 2.1 vs .net core 3.0 【发布时间】:2020-10-27 20:09:22 【问题描述】:我在 .net 标准 2.0 中编写了一个 dll。假设只是通过StreamWriter
将数据写入文本文件。
注意:我知道下面的代码可以用更好的方式编写。此代码只是测试库。
DLL 代码:
public class WriteIntoLog
private StreamWriter _streamWriter;
public void WriteMsgToFile(string message)
try
bool close = true;
if (_streamWriter == null || _streamWriter.BaseStream == null)
_streamWriter = new StreamWriter("Test.txt", true);
_streamWriter.WriteLine(message);
if (close)
CloseLogFileStream(false);
catch (IOException ioEx)
throw new Exception(ioEx.Message);
catch (Exception ex)
throw new Exception(ex.Message);
public void CloseLogFileStream(bool dispose)
if (_streamWriter != null)
_streamWriter.Close();
if (dispose)
_streamWriter = null;
并从.net core 2.1
编写的控制台应用程序调用此dll
class TStreamWriter
static void Main(string[] args)
WriteIntoLog log = new WriteIntoLog();
for (int i = 0; i < 10; i++)
log.WriteMsgToFile($"Loop no: i.ToString()");
Console.WriteLine("Hello World!");
现在此代码按预期运行,但是当我将控制台应用程序的目标平台更改为 .net core 3.0
时,代码返回“无法写入已关闭的 TextWriter”的异常。
那么为什么它在.net core 2.1
中运行控制台应用程序时不返回异常。
【问题讨论】:
没有区别。WriteIntoLog
虽然有问题,但无论它是否存在,都会使用相同的 cached 流。鉴于WriteMsgToFile
之外不需要此流,因此没有理由将其存储在字段中
为什么要编写自己的日志记录代码,而不是使用像 Serilog 或 .NET Core 自己的 Microsoft.Extensions.Logging 这样的库?
顺便说一句,你可以用File.AppendAllText(somePath,message + "\n");
替换所有这些代码
@PanagiotisKanavos 存在一些差异,因为相同的代码在 2.1 中运行良好,而在 3.0 中出现异常。
并非如此 - 实例已被处置,已死亡,不打算再次使用。事实上,我很惊讶当您尝试访问 BaseStream
时却没有收到 ObjectDisposedException
。
【参考方案1】:
问题是您正在创建WriteIntoLog
的实例,然后多次调用它的函数。第一次之后,由于bool close
始终是true
,因此在流上调用Close()
。未来的循环迭代 (2 - 10) 尝试使用关闭的流进行写入,因为 _streamWriter
已关闭并且此代码将不再评估为 true:
if (_streamWriter == null || _streamWriter.BaseStream == null)
_streamWriter = new StreamWriter("Test.txt", true);
【讨论】:
都是正确的,但是并没有说明两个目标框架的区别。 @Maarten 没有调查过,但我几乎可以保证,一旦流关闭,_streamWriter.BaseStream
在核心 2.1 中为空,在 3.0 中不为空
不错,确实是这样。
@Haney 你是对的。 _streamWriter.BaseStream
在 3.0 中不为空。这意味着两个版本中StreamWriter
类的实现存在差异
@vikky 为什么要写这样的代码?它是一个已处置的类,绝对不能保证它的成员(如 BaseStream)会处于一种或另一种状态。【参考方案2】:
您遇到问题是因为 _streamWriter
已关闭,但不是 null
。
你可以简单地做到这一点。
using (StreamWriter write = new StreamWriter(""))
...//Add your code here
【讨论】:
这里没有说明两个目标框架的区别。 @Maarten 框架没有区别。 OP 使用错误代码 并且 尝试通过 BaseStream 触及实现细节。无法保证 disposed writer 的流会处于一种或另一种状态 @Maarten 我同意,但这发生在代码中的错误上。所以如果我们解决了这个问题,他就不会遇到这样的错误。以上是关于从 .net core 2.1 与 .net core 3.0 调用时的 StreamWriter 类行为的主要内容,如果未能解决你的问题,请参考以下文章
从 .NET Core 2.1 降级到 .NET 4.7.1 时如何使用 IApplicationBuilder 和 IServiceCollection?
ASP.NET Core 2.1 中的 HttpClientFactory (Part 3) 使用Handler实现传出请求中间件
从asp.net core 2.1中的控制器访问BackgroundService
ZXing QrCode 渲染器异常与 .Net Core 2.1