J'ai un problème avec un log4netappender personnalisé, un agent de backgound et une zone de texte enrichi wpf. La zone de texte riche n'est pas mise à jour correctement lorsque je me connecte à partir d'un thread backgound.Problème d'appender personnalisé Log4net avec le répartiteur?
Lorsque j'appelle l'enregistreur du thread principal, le texte est correctement enregistré dans le composant d'interface utilisateur (la zone de texte enrichi). Mais quand j'appelle le logger d'un BackgroundWorker, l'événement de Logger Append est levé mais l'interface utilisateur (le richtextbox) n'est jamais mise à jour ... Pourquoi cela?
Merci pour toute aide!
Voici mon code d'une fenêtre principale contenant un bouton pour lancer BackgroundWorker et un contrôle personnalisé 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);
}
...}
Voici mon « WpfRichTextBoxAppender », un appender personnalisé pour log4net afficher des messages sur un contrôle personnalisé contenant un RichTextbox WPF:
/// <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();
}
}
}