title: Backgroundworker updating log on the ui
body: <p>I have a wpf application with a text box in the main window that is supposed to be used to display logging information while the user runs a long process. </p>
  
  <pre><code>&lt;TextBox Grid.Row="1" Margin="10,10,10,10" AcceptsReturn="True" Name="txtLogging" TextWrapping="WrapWithOverflow" 
                   Text="{Binding Path=LogText, Mode=TwoWay}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" /&gt;
  
  public string LogText
  {
      get { return _logText; }
      set
      {
          _logText = value;
          OnPropertyChanged();
      }
  }
  </code></pre>
  
  <p>One of the buttons on the ui kicks off a process that takes a minimum of 30 seconds, and sometimes up to a few hours.  Needless to say, running this on a background worker is preferred.  The issue is that the logging class in the program is being created on the UI thread and has to be accessed during the worker's execution to update the UI with the log of what is currently happening.</p>
  
  <p>The logger looks like this;</p>
  
  <pre><code>using System;
  using System.IO;
  
  namespace BatchInvoice
  {
      public enum LoggingLevel
      {
          Verbose = 0,
          Info = 1,
          Warning = 2,
          Error = 3
      }
      public sealed class Logger
      {
  
          string _logFile;
          static Logger() { }
          public bool LogToDataBase = false;
          public bool LogToFile = true;
          public bool LogToScreen = false;
          private Logger()
          {
              //string filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
              string filePath = Directory.GetCurrentDirectory();
              filePath = filePath + @"\LogFiles";
              string extension = ".log";
              if (!Directory.Exists(filePath))
              {
                  Directory.CreateDirectory(filePath);
              }
              /*string currentDir = Environment.CurrentDirectory;
              DirectoryInfo directory = new DirectoryInfo(currentDir);
              string fullDirectory = directory.FullName;*/
              string date = (DateTime.Now).ToString("yyyyMMddHHmmss");
              _logFile = filePath + "\\" + date + extension;
              minimumLoggingLevel = LoggingLevel.Info;
          }
          private LoggingLevel minimumLoggingLevel;
          public static void SetMinimumLoggingLevel(LoggingLevel minimum)
          {
              Instance.minimumLoggingLevel = minimum;
          }
          public static LoggingLevel GetMinimumLoggingLevel()
          {
              return Instance.minimumLoggingLevel;
          }
          private static readonly Logger instance = new Logger();
          public static Logger Instance
          {
              get
              {
                  return instance;
              }
          }
          public static void Write(string content)
          {
              using (StreamWriter fileWriter = File.AppendText(Instance._logFile))
              {
                  fileWriter.WriteLine(content);
              }
          }
          public static void Write(string content, LoggingLevel warningLevel)
          {
              if (Instance.minimumLoggingLevel &lt;= warningLevel)
              {
                  if (Instance.LogToFile)
                  {
                      using (StreamWriter fileWriter = File.AppendText(Instance._logFile))
                      {
                          fileWriter.WriteLine(warningLevel.ToString() + ": " + content);
                      }
                  }
                  if (Instance.LogToScreen)
                      ScreenLogging.Write(content, warningLevel);
                  if (Instance.LogToDataBase)
                  {
                      //enter database loggign code here.
                  }
              }
          }
      }
  }
  
  using System.Windows;
  using System.Windows.Controls;
  
  namespace BatchInvoice
  {
      public class ScreenLogging
      {
          private static ScreenLogging _instance;
          private ScreenLogging() { }
          public static ScreenLogging Instance
          {
              get
              {
                  if(_instance == null)
                  {
                      _instance = new ScreenLogging();
                  }
                  return _instance;
              }
          }
          private TextBox _target;
          public static void SetTarget(TextBox target)
          {
              Instance._target = target;
          }
          public static void Write(string content, LoggingLevel warningLevel)
          {
              //MessageBox.Show(content, warningLevel.ToString());
              Instance._target.AppendText(warningLevel.ToString() + ": " + content + "\n");
          }
      }
  }
  </code></pre>
  
  <p>(Yes there is a reason the screenlogging is separated into a different class, but I really hope I don't have to change that)  What can I do to make the calls to this logging class reflect on the UI from within the background worker?  Should I change the LogText property to read from an external file or something along those lines?  Currently I don't have the background worker implemented, so the logging only shows after the task is completed, but I need to be able to monitor its progress while its running.  When I tried putting it into a background worker it errored when it hit a line of code that tried to access the logger.  </p>