【问题标题】:StreamWriter class behavior when call from .net core 2.1 vs .net core 3.0从 .net core 2.1 与 .net core 3.0 调用时的 StreamWriter 类行为
【发布时间】: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

标签: c# .net-core .net-standard .net-core-3.0 .net-core-2.1


【解决方案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 我同意,但这发生在代码中的错误上。所以如果我们解决了这个问题,他就不会遇到这样的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
  • 2019-08-03
  • 1970-01-01
相关资源
最近更新 更多