1

我创建了一个事件驱动的记录器,当从另一个线程调用时它似乎有问题。我怎样才能使它线程安全?

这是记录器类:

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);
    }
}

在我的表单类中,我通过以下两种方式启动它:

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();
}
4

2 回答 2

3

您必须在 UI 线程中调用 MyLogger_LogAdded 的主体。在调用 rtb_logger 的方法或属性时尝试使用 Dispatcher.BeginInvoke()。

请参阅C#:线程安全的 Richtextbox 事件记录方法?

于 2013-03-03T07:16:33.633 回答
0
private delegate void MYLOGGEREVENT(object sender, EventArgs e);
private void MyLogger_LogAdded(object sender, EventArgs e)
{
if (InvokeRequired)
            {
                BeginInvoke(new MYLOGGEREVENT(MyLogger_LogAdded), new object[]{sender, e});
            }
else{
    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();
}
}

试试这个。

于 2013-03-03T08:29:29.180 回答