1

I'm trying to use a Form with TextBox as an appender for log4net but TextBox simply do not append text. I see, that AppendText method is called (from UI thread), property Text is changed, but at some time appended value just dissapearing and Text property is still empty.

I'm not sure, if it is log4net issue, but the problem appears only with logs.

Application start-up and form (InvokeIfRequired is very common extension from here: Automating the InvokeRequired code pattern):

public partial class FormMain : Form, IAppender
{
    readonly ILog log;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        XmlConfigurator.Configure();

        Application.Run(new FormMain());
    }
    public FormMain()
    {
        log = LogManager.GetLogger(typeof(FormMain));

        InitializeComponent();
    }

    public void DoAppend(LoggingEvent le)
    {
        tbLog.AppendText("This msg is NOT shown");

        tbLog.InvokeIfRequired(() =>
            {
                // NOT SHOWN
                tbLog.AppendText(string.Format("{0:yyyyMMdd HH:mm:ss.fff}> [{1}] [{2}] {3}", le.TimeStamp, le.LoggerName, le.Level, le.MessageObject));
            });
    }

    private void bTestLog_Click(object sender, EventArgs e)
    {
        tbLog.AppendText("This msg is shown");

        log.Debug("Test logs");
    }
}

App.config:

<?xml version="1.0"?>
<configuration>

  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>

  <log4net>
    <appender name="FileAppender" type="log4net.Appender.FileAppender,log4net">
      <file value="mylogfile.txt" />
      <appendToFile value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
      </layout>
    </appender>

    <appender name="FormMain" type="Client.FormMain,Client" />

    <root>
      <level value="DEBUG"/>
      <appender-ref ref="FormMain"/>
    </root>
  </log4net>

</configuration>

AssemblyInfo.cs:

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

After clicking the button bTestLog only one message appears on tbLog: "This msg is shown"

UPD I've monitored Text property of tbLog and found it very strange. After first appending, as expected, it is "This msg is shown". But when program enters DoAppend method, it's empty. Further appends change it as expected, but when back to bTestLog_Click it's "This msg is shown" again!

Community
  • 1
  • 1
astef
  • 8,575
  • 4
  • 56
  • 95
  • Is it possible that the first `AppendText` call within `DoAppend` is generating an exception because of being on the wrong thread? If you remove that call, is the one within `InvokeIfRequired` used? – Jon Skeet Apr 22 '13 at 09:52
  • No, there is no exception. Debug=>Exceptions are all on. And I'm walking through it with Debugger, everything is OK and InvokeIfRequired is called properly – astef Apr 22 '13 at 10:10
  • And yes, if I remove first line in `DoAppend` it still doesn't work – astef Apr 22 '13 at 10:12
  • @JonSkeet Still not used to comment system... Now you're notified – astef Apr 22 '13 at 10:42

1 Answers1

2

Okay, I think I've got it.

I strongly suspect that this:

<appender name="FormMain" type="Client.FormMain,Client" />

... is getting log4net to create a new instance of FormMain. So you've got one instance being shown, but there's another form which isn't being shown, but is receiving append calls.

You should be able to see that in the debugger - if you put breakpoints in both DoAppend and bTestLog_Click, you'll see the instance that the methods are being invoked on being different.

I don't know the best way of hooking log4net into an existing object, but you may find that you can just programmatically add an appender in log4net; you should look at the API for more details.

As an aside, I'd probably separate the concerns of "being an appender" and "being a form" - I'd create an implementation of IAppender which appends to a text box which is provided in its constructor, and then pass the relevant text box from the form when you construct the appender. That's a slightly different matter though :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • i have a question for you.can i ask now – PSR Apr 22 '13 at 12:37
  • @PSR: Unless it's actually directly related to the original question or this answer, you should ask a separate new question. – Jon Skeet Apr 22 '13 at 12:44
  • @PSR: And you think that adding comments on *completely unrelated* answers is a good way to get attention? It really isn't. (Improve your question instead.) – Jon Skeet Apr 22 '13 at 12:48
  • i asked for the reasons .But no one is responding.I have really in confusion.can i send email to you what you specified in your profile – PSR Apr 22 '13 at 12:48
  • @PSR: I fail to see why you think that means it's okay to add comments on unrelated answers. And no, please *don't* send me an email about this. Ask a *good* question, and you won't get downvotes. Read http://tinyurl.com/so-hints – Jon Skeet Apr 22 '13 at 12:49
  • 3
    @PSR: No, I'm busy. I am *not* a personal assistant to be called on, particularly via offtopic comments. If I happen to see the question and it's good, so be it - but if I don't, I don't. – Jon Skeet Apr 22 '13 at 12:57