2010-12-13 3 views
1

У меня возникла проблема с пользовательским log4netappender, backgound worker и текстовым полем, богатым wpf. Богатое текстовое поле не обновляется корректно, когда я регистрирую из обратного потока.Задача пользовательского приложения Log4net с диспетчером?

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

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

Вот мой код из главного окна, содержащие кнопки для запуска BackgroundWorker и таможенного контроля nammed «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, который отображает сообщения о пользовательский элемент управления, содержащий МОФ 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(); 
     } 
    } 


} 

ответ

0

Я не использовал WPF, поэтому я не могу комментировать, почему, в частности, это не работает, как вы ожидаете. Тем не менее, я нашел это link to a blog posting, где peteohanlon показывает, как сделать log4net Appender, который перенаправляет свой вывод в текстовое поле WPF. Он специально упоминает использование INotifyPropertyChanged. Может быть, что-то в его посте поможет вам.

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

BackgroundWorker & Timer, reading only new lines of a log file?

0

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

  _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); 
Смежные вопросы