c#“无法写入已关闭的TextWriter。”在一个字符串对象?

时间:2013-11-01 13:34:05

标签: c# 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 <抛出异常/ strong>调用命令对象!!

这是否可能或Visual Studio意味着输出文件?如果是这样,为什么“if(Log_Screen_File == null)”不起作用?

谢谢

1 个答案:

答案 0 :(得分:3)

致电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线程上执行。但是锁不会伤害任何东西,并且不会影响性能。