0

许多用户都出现了这个错误,但在我的情况下,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)”语句可以完成这项工作(并且在一般情况下它可以工作)但现在异常是由调用命令上的文本对象引发的!

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

谢谢你

4

1 回答 1

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 线程上执行。不过,锁不会伤害任何东西,也不会影响性能。

于 2013-11-01T13:38:41.027 回答