字符串对象的 C# "Cannot write to a closed TextWriter."?



这个错误已经出现在许多用户身上,但在我的情况下,Visual studio似乎指向一个字符串对象。我的代码如下:

protected delegate void DPrint_To_LogScreen(string Text, bool NewLine);
protected void Print_To_LogScreen(string Text, bool NewLine)
{
    if (InvokeRequired)
        Invoke(new DPrint_To_LogScreen(Print_To_LogScreen), new object[] { Text, NewLine }); // exception thrown here from the Text string 
    else
    {
        LogScreen.AppendText(Convert.ToString(DateTime.Now) + "  ->  " + Text + (NewLine ? System.Environment.NewLine : ""));
        if (Log_Screen_File == null)
        {
            Log_Screen_File = new StreamWriter(@"Global.log", true);
            Log_Screen_File.WriteLine(Convert.ToString(DateTime.Now) + "  ->  " + Text);
            Log_Screen_File.Close();
        }
        else
        {
            lock (Log_Screen_File)
                Log_Screen_File.WriteLine(Convert.ToString(DateTime.Now) + "  ->  " + Text);
        }
    }
}

我通常想从不同的地方和线程调用函数Print_To_LogScreen

我期望"if (Log_Screen_File == null)"语句可以完成这项工作(并且在一般情况下它可以工作),但现在异常是由调用命令上的 Text 对象引发的!!

这甚至可能还是Visual Studio意味着输出文件?如果是这样,为什么"if (Log_Screen_File == null)"不起作用?

谢谢

调用Close不会将其设置为 null 。另外,您应该在此处使用using。将代码更改为:

    if (Log_Screen_File == null)
    {
        using (Log_Screen_File = new StreamWriter(@"Global.log", true))
        {
            Log_Screen_File.WriteLine(Convert.ToString(DateTime.Now) + "  ->  " + Text);
        }
        Log_Screen_File = null;
    }

它具有与上述代码相同的功能,只是它不会引发您当前获得的异常。

不过,很难说你真正想发生什么。在我看来,你似乎有一个潜在的问题。假设线程 A 和线程 B 正在执行。线程 A 看到该Log_Screen_File == null并创建它。然后线程 B 获取一个时间片并看到该文件存在。然后线程 A 获取另一个时间片,写入文件并关闭它。然后,线程 B 将尝试写入不存在的文件。

如果此代码将由多个线程使用,则必须确保整个操作是原子的。我建议:

private readonly object logLock = new object();
protected void Print_To_LogScreen(string Text, bool NewLine)
{
    if (InvokeRequired)
        Invoke(new DPrint_To_LogScreen(Print_To_LogScreen), new object[] { Text, NewLine }); // exception thrown here from the Text string 
    else
    {
        lock (logLock)
        {
            LogScreen.AppendText(Convert.ToString(DateTime.Now) + "  ->  " + Text + (NewLine ? System.Environment.NewLine : ""));
            if (Log_Screen_File == null)
            {
                using (Log_Screen_File = new StreamWriter(@"Global.log", true))
                {
                    Log_Screen_File.WriteLine(Convert.ToString(DateTime.Now) + "  ->  " + Text);
                }
                Log_Screen_File = null;
            }
            else
            {
                Log_Screen_File.WriteLine(Convert.ToString(DateTime.Now) + "  ->  " + Text);
            }
        }
    }
}

但是你真的想每次都打开和关闭文件吗?你不会这样做吗:

            if (Log_Screen_File == null)
            {
                Log_Screen_File = new StreamWriter(@"Global.log", true);
            }
            Log_Screen_File.WriteLine(Convert.ToString(DateTime.Now) + "  ->  " + Text);

当然,假设您在程序退出时关闭日志文件。

想想看,您可能根本不需要锁,因为该方法正在 UI 线程上执行。但是,锁不会造成任何伤害,也不会影响性能。

相关内容

  • 没有找到相关文章

最新更新