1

この静的ログ クラスを作成して、多くのスレッドですべてのステータスを記録しました。ときどき、(プログラムが書き込んでいる) ログ ファイルが占有されているという例外が発生しました。他のスレッドが同時にファイルを書き込んでいたようです。この例外を回避するために、このすべての作業を UI スレッドに呼び出しましたが、それでも発生します。なにか提案を?ありがとう。

ところで、lock(mLog) を使用してこの問題を回避できることはわかっていますが、なぜこれが発生するのか疑問に思っています。UI スレッドで 2 つの Log.UpdateLog 関数を同時に実行してはいけません。よろしいですか?

public partial class LogForm : Form
{
    private StringBuilder mLog;

    public LogForm()
    {
        InitializeComponent();

        mLog = new StringBuilder();
    }

    public void Write(string msg, bool save)
    {
        mLog.Insert(0, msg + "\r\n\r\n" + "-----------------------------------------------------------------------" + "\r\n\r\n");

        if (save)
        {
            SaveFile();
        }
    }

    private void SaveFile()
    {
        FileStream file;
        file = new FileStream(Application.StartupPath + @"\LOG.txt", FileMode.Create);
        StreamWriter sw = new StreamWriter(file);
        sw.Write(mLog.ToString());
        sw.Close();
        file.Close();
    }


}

public static class Log
{
    private delegate void mUIInvoke(string msg, bool save);

    private static LogForm mLogForm = new LogForm();

    public static void Write(string msg, bool save)
    {
        msg += "\r\nTIME:" + DateTime.Now.ToShortDateString() + "  " + DateTime.Now.ToShortTimeString();

        if (mLogForm.InvokeRequired)
        {
            mUIInvoke invoke = new mUIInvoke(UpdateLog);
            mLogForm.BeginInvoke(invoke, new object[] { msg, save });
        }
        else
        {
            UpdateLog(msg, save);
        }
    }


    private static void UpdateLog(string msg, bool save)
    {
        mLogForm.Write(msg, save);
    }

}
4

4 に答える 4

0

理論は次のとおりです。ログフォームは静的変数を介してアクセスされます。この変数は Log クラスの最初のアクセスで初期化され、この最初のアクセスは非 UI スレッドから発生する可能性があります。そのため、フォームが非 UI スレッドで作成される可能性があり、これが発生している問題の原因になる可能性があります。

于 2013-04-18T20:18:21.110 に答える
0

私は友人の一人と一緒にこの問題を解決しました。実際には、 mLogForm.InvokeRequired が呼び出される前に mLogForm が表示されたことがないためです。表示されていない場合、mLogForm のハンドルはありません。ハンドルがないと、正しい方法で mLogForm.InvokeRequired を呼び出すことができません。つまり、他のスレッドが Log.Write を呼び出しても false が返され、UpdateLog メソッドを実行している多くのスレッドがこの問題を引き起こしました。表示されていないフォームへの呼び出しを確実に使用できるようにするには、このフォームを作成するときに CreateHandle() を使用します。ありがとう。

于 2013-04-19T04:26:30.607 に答える
0

UI スレッドの問題ではありません。問題は (主に) SaveFile メソッドにあります。2 つの異なるスレッドがこのメソッドにアクセスしようとすると、そのファイルがまだ他のスレッドによって使用されていることがわかります。単純なロックで問題を解決できます。

したがって、呼び出しmLogForm.Write ているスレッド A を想像してみてください。メソッドに入り、中断することなく SaveFile メソッドに到達し、ファイル ストリームを開きますが、この時点で中断され、OS はスレッド B を実行することを決定します。前スレは休止中

于 2013-04-18T20:10:29.747 に答える