Проблема пользовательского приложения Log4net с диспетчером? - PullRequest
1 голос
/ 13 декабря 2010

У меня проблема с пользовательским log4netappender, рабочим фоном и текстовым полем wpf. Поле расширенного текста не обновляется правильно, когда я вхожу из фоновой темы.

Когда я вызываю регистратор из основного потока, текст корректно записывается в компонент пользовательского интерфейса (richtextbox). Но когда я вызываю регистратор из BackgroundWorker, возникает событие добавления регистратора, но пользовательский интерфейс (richtextbox) никогда не обновляется ... Почему это?

Спасибо за любую помощь!

Вот мой код основных окон, содержащих кнопку для запуска backgroundworker и пользовательский элемент управления с именем RichTraceBox:

     private static readonly log4net.ILog _logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

     TraceBox TheTraceBox;

     public MainPanel()
    {
        InitializeComponent();

        // Configure Log4Net
        Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
        hierarchy.Root.RemoveAllAppenders(); /*Remove any other appenders*/           
        //// .... create and configure appender ...///
        WpfRichTextBoxAppender notify = new WpfRichTextBoxAppender(this.TheTraceBox);
        PatternLayout layout = new PatternLayout();
        layout.ConversionPattern = "%d [%t] %-5p %c %m%n";
        notify.Layout = layout;
        notify.ActivateOptions();


        log4net.Config.BasicConfigurator.Configure(notify);
        _logger.Debug("Correctly logged");

        }

 private void button1_Click(object sender, RoutedEventArgs e)
    {
        BackgroundWorker checkGraphlongWorker = new BackgroundWorker();
        checkGraphlongWorker.DoWork += new DoWorkEventHandler(checkGraphlongWorker_DoWork);
        checkGraphlongWorker.RunWorkerAsync();

    }

    void checkGraphlongWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        Thread.Sleep(2000);
        _logger.Debug("This is never Logged....");

        this.TheTraceBox.DisplayOnTraceBox("...But this is corectly displayed ???!!", Brushes.Red);


        }
...}

Вот мой "WpfRichTextBoxAppender", пользовательский appender для log4net, который отображает сообщения в пользовательском элементе управления, содержащем wpf richTextBox:

   /// <summary>
/// Description of RichTextBoxAppender.
/// </summary>
public class WpfRichTextBoxAppender : AppenderSkeleton
{
    #region Private Instance Fields
    private TraceBox richTextBox = null;
    private int maxTextLength = 100000;
    #endregion

    private delegate void UpdateControlDelegate(LoggingEvent loggingEvent);

    #region Constructor
    public WpfRichTextBoxAppender(TraceBox myRichTextBox)
        : base()
    {
        richTextBox = myRichTextBox;
    }
    #endregion


    protected override void Append(LoggingEvent[] loggingEvents)
    {
        base.Append(loggingEvents);
    }

    protected override void Append(LoggingEvent loggingEvent)
    {

        if (richTextBox != null)
        {
            // There may be performance issues if the buffer gets too long
            // So periodically clear the buffer
            if (richTextBox.TextLenght > maxTextLength)
            {
                richTextBox.ClearTrace();
            }
            Brush color = Brushes.Black;
            if (loggingEvent.Level == Level.Alert)
                color = Brushes.Orange;
            else if (loggingEvent.Level == Level.Critical)
                color = Brushes.DarkOrange;
            else if (loggingEvent.Level == Level.Error)
                color = Brushes.Red;
            else if (loggingEvent.Level == Level.Fatal)
                color = Brushes.Red;
            else if (loggingEvent.Level == Level.Warn)
                color = Brushes.OrangeRed;
            this.richTextBox.DisplayOnTraceBox(RenderLoggingEvent(loggingEvent), color);
        }
    }
}


 public partial class TraceBox : UserControl
{
    public TraceBox()
    {
        InitializeComponent();
        this.Visibility = System.Windows.Visibility.Visible;
    }        

    private void Button_Clear_Click(object sender, RoutedEventArgs e)
    {
        this.ClearTrace();
        //this.Output.Text = "";
    }


    public void ClearTrace()
    {
        FlowDocument myFlowDoc = new FlowDocument();
        this.ConsoleOutputTextBox.Document = myFlowDoc;
    }


    public int TextLenght {
       get
       {
           TextRange tr = new TextRange(this.ConsoleOutputTextBox.Document.ContentStart, this.ConsoleOutputTextBox.Document.ContentEnd);
           return tr.Text.Length;
        }
    }

    private delegate void DisplayOnTraceBoxDel(object message, Brush messageColor);
    public void DisplayOnTraceBox(object message, Brush messageColor)
    {            
        if (!this.ConsoleOutputTextBox.Dispatcher.CheckAccess())
        {
            this.ConsoleOutputTextBox.Dispatcher.Invoke(new DisplayOnTraceBoxDel(DisplayOnTraceBox), DispatcherPriority.DataBind, new object[] { message, messageColor });
        }
        else
        {
            TextRange tr = new TextRange(this.ConsoleOutputTextBox.Document.ContentEnd, this.ConsoleOutputTextBox.Document.ContentEnd);
            tr.Text = message.ToString();
            tr.ApplyPropertyValue(TextElement.FontFamilyProperty, "Consolas");
            tr.ApplyPropertyValue(TextElement.FontSizeProperty, 10D);
            tr.ApplyPropertyValue(Paragraph.MarginProperty, new Thickness(0));
            //tr.ApplyPropertyValue(Paragraph.BackgroundProperty, "LightSteelBlue");
            tr.ApplyPropertyValue(TextElement.ForegroundProperty, messageColor);
            this.ConsoleOutputTextBox.UpdateLayout();
        }
    }


}

Ответы [ 2 ]

0 голосов
/ 09 декабря 2013

У меня была такая же проблема, и я решил ее с помощью пункта абзаца, так что ...

            _textBox.Dispatcher.BeginInvoke(new Action<string>(s =>
            {      
                Paragraph p = new Paragraph();
                p.Inlines.Add(new Run(s) { Foreground = Brushes.Red });
                ((RichTextBox)_textBox).Document.Blocks.Add(p);
            }), msg);
0 голосов
/ 13 декабря 2010

Я не использовал WPF, поэтому я не могу прокомментировать, почему, в частности, это работает не так, как вы ожидаете.Однако я нашел ссылку на запись в блоге , где peteohanlon показывает, как создать приложение log4net, которое перенаправляет его вывод в текстовое поле WPF.Он специально упоминает использование INotifyPropertyChanged.Возможно, что-то в его посте поможет вам.

Кроме того, здесь есть ссылка на другой ответ, который я разместил здесь на SO, который ссылается на несколько основанных на TextBox приложений (я не думаю, что кто-то из них является WPF,к сожалению):

BackgroundWorker & Timer, чтение только новых строк файла журнала?

...