別のスレッドから呼び出されたときに問題があると思われるイベント ドリブン ロガーを作成しました。どうすればスレッドセーフにできますか?
LoggerClass は次のとおりです。
public static class MyLogger
{
private static List<string> log = new List<string>();
public static event EventHandler LogAdded;
private static string indent = "";
public static void Log(string message)
{
log.Add(indent + message);
if (LogAdded != null)
LogAdded(null, EventArgs.Empty);
}
}
私のフォーム クラスでは、次の 2 つの方法で開始しました。
public frm_main()
{
InitializeComponent();
MyLogger.LogAdded += new EventHandler(MyLogger_LogAdded);
}
そして、クラッシュが発生したイベントの進行状況は次のとおりです。
private void MyLogger_LogAdded(object sender, EventArgs e)
{
int length = rtb_logger.TextLength; // at end of text
string prefix = string.Format("{0:d3}: ", ++logindex);
string ToAppend = prefix + MyLogger.GetLastLog();
rtb_logger.AppendText(ToAppend);
if (ToAppend.Contains("Alert -"))
{
rtb_logger.SelectionStart = length;
rtb_logger.SelectionLength = ToAppend.Length;
rtb_logger.SelectionColor = Color.Red;
}
rtb_logger.AppendText(Environment.NewLine);
rtb_logger.SelectionStart = rtb_logger.TextLength;
rtb_logger.ScrollToCaret();
EnableControls();
}
クラッシュは、バックグラウンド ワーカーからの次の呼び出しで、「テキストの最後で」とコメントされた上記の最初の行で発生します。
MyLogger.Log("Sending cmd: \"" + strCmdText + "\" to CMD.exe.");
MyLogger クラスをスレッドセーフにするにはどうすればよいですか?
編集: SeeSharp ソリューションを使用すると、変更されたコードは次のとおりです。
private void MyLogger_LogAdded(object sender, EventArgs e)
{
if (rtb_logger.InvokeRequired)
{
rtb_logger.BeginInvoke(new Action(delegate {
MyLogger_LogAdded(sender, e);
}));
return;
}
int length = rtb_logger.TextLength; // at end of text
string prefix = string.Format("{0:d3}: ", ++logindex);
string ToAppend = prefix + MyLogger.GetLastLog();
rtb_logger.AppendText(ToAppend);
if (ToAppend.Contains("Alert -"))
{
rtb_logger.SelectionStart = length;
rtb_logger.SelectionLength = ToAppend.Length;
rtb_logger.SelectionColor = Color.Red;
}
rtb_logger.AppendText(Environment.NewLine);
rtb_logger.SelectionStart = rtb_logger.TextLength;
rtb_logger.ScrollToCaret();
EnableControls();
}