Пользовательский вывод System.Diagnostics.TraceListener в RichTextBox зависает - PullRequest
1 голос
/ 31 августа 2009

У меня есть RichTextBox, который я использую в качестве вывода из пользовательского TraceListener, показанного ниже: Беда в том, что кажется, что это тупик, если кто-то пишет информацию отладки / трассировки из других потоки, в то время как диалоговое окно GUI также пытается записать информацию отладки / трассировки.

Кто-нибудь хочет указать на некоторые очевидные ошибки здесь? :

class MyTraceListener : TraceListener
{
    private RichTextBox output;

    public MyTraceListener (RichTextBox output) {
        this.Name = "DebugTrace";
        this.output = output;
    }


    public override void Write(string message) {
        Action append = delegate() { output.AppendText(message); };
        if (output.InvokeRequired) {
            IAsyncResult result = output.BeginInvoke(append);
            output.EndInvoke(result);
        } else {
            append();
        }
    }

    public override void WriteLine(string message) {
        Action append = delegate() { output.AppendText(message + "\r\n"); };
        if (output.InvokeRequired) {
            IAsyncResult result = output.BeginInvoke(append);
            output.EndInvoke(result);
        } else {
            append();
        }

    }
}

Ответы [ 4 ]

1 голос
/ 31 августа 2009

Вот что, вероятно, происходит:

  • Поток 1: получает EndInvoke (); ожидая выполнения делегата в поток графического интерфейса.
  • Поток GUI: блокируется в System.Diagnostics.Trace.WriteLine где-то (афаик трассировочная система использует замки, чтобы быть потокобезопасным.)
  • Поток 1: будет заблокирован навсегда, поскольку поток GUI заблокирован и не может завершить выполнение делегата.

Вызов только Invoke, скорее всего, не решит проблему, так как Invoke блокирует, пока не завершится работа делегата.

Вызов только BeginInvoke должен решить проблему блокировки, BeginInvoke просто инициирует асинхронный вызов потока GUI, не дожидаясь его завершения, покидая систему трассировки и разблокируя поток GUI. (Хотя я не уверен, что не стоит вызывать EndInvoke.

0 голосов
/ 31 августа 2009

Я бы посоветовал вам использовать простую очередь производителя / потребителя здесь. Ваш ответ на запись трассировки должен состоять в том, чтобы добавить строку в очередь, затем в форме, отображающей данные, вы можете использовать System.Windows.Forms.Timer () для очистки очереди и отображения текста. В противном случае вы столкнетесь с проблемами и / или задержками в работающей программе.

0 голосов
/ 31 августа 2009

Что если вы попробуете использовать этот подход?

public override void Write(string message) {
    if (this.output.InvokeRequired)
    {
        this.output.Invoke((MethodInvoker)delegate
        {
            this.output.AppendText(message);
        });
     }
     else
     {
         this.output.AppendText(message);
     }
}
0 голосов
/ 31 августа 2009

Просто подумайте, попробуйте использовать Control.Invoke, а не BeginInvoke. IE:

class MyTraceListener : TraceListener
{
        private RichTextBox output;

        public MyTraceListener (RichTextBox output) {
                this.Name = "DebugTrace";
                this.output = output;
        }


        public override void Write(string message) {
                Action append = delegate() { output.AppendText(message); };
                if (output.InvokeRequired) {
                        output.Invoke(append);
                } else {
                        append();
                }
        }

        public override void WriteLine(string message) {
                Action append = delegate() { output.AppendText(message + "\r\n"); };
                if (output.InvokeRequired) {
                        output.Invoke(append);
                } else {
                        append();
                }

        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...