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)」ステートメントが機能することを期待していましたが (一般的には機能します)、invoke コマンドでTextオブジェクトによって例外がスローされました!!

これは可能ですか、それとも 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 に答える