title: WPF - Updating Label Content During Processing
body: <p>Well I've tried several methods of getting this to work, background worker, Dispatcher.Invoke, threading within the called class and nothing seems, to work. The best solution so far is an Extension method which calls the invoke of the control. Also I've tried avoid passing the data for the label through my event classes and simply invoking within my processing code, however this made no difference.</p>
  
  <p>In regards to the background component, I kept getting exceptions saying the background worker was busy, so I instantiated the class several times, however the label only visibly changed once the entire operation had been complete.</p>
  
  <p>I've removed my previous code, here's everything that is relevant, as it seems the issue is difficult to resolve.</p>
  
  <p><strong>Method Being Called</strong></p>
  
  <pre><code> private void TestUris()
          {
              string text = new TextRange(rtxturis.Document.ContentStart, rtxturis.Document.ContentEnd).Text;
              string[] lines = Regex.Split(text.Remove(text.Length - 2), "\r\n");
  
              foreach (string uri in lines)
              {
                  SafeUpdateStatusText(uri);
                  bool result;
                  string modUri;
  
                  if (!uri.Contains("http://"))
                  {
                      modUri = uri;
                      result = StoreData.LinkUriExists(new Uri("http://" + modUri));
                  }
                  else
                  {
  
                      modUri = uri.Substring(7);
                      result = StoreData.LinkUriExists(new Uri(uri));
                  }
  
                  if (!result)
                  {
                      Yahoo yahoo = new Yahoo();
                      yahoo.Status.Sending += (StatusChange);
                      uint yahooResult = 0;
  
                      yahooResult = yahoo.ReturnLinkCount(modUri);
  
                      if (yahooResult &gt; 1000 )
                      { results.Add(new ScrapeDetails(Guid.NewGuid(), modUri, 1000, "Will be processed", true)); }
                      else
                      { results.Add(new ScrapeDetails(Guid.NewGuid(), modUri, (int)yahooResult, "Insufficient backlinks", false)); }
  
                  }
                  else
                  {
                      results.Add(new ScrapeDetails(Guid.NewGuid(), modUri, 0, "Previously been processed", false));
                  }
              }
  
  
              foreach (var record in results)
              {
                  dgvresults.Items.Add(record);
  
              }
  
              EnableStartButton();
  
          }
  </code></pre>
  
  <p><strong>Yahoo Class</strong></p>
  
  <pre><code>public class Yahoo
      {        
  
          /// &lt;summary&gt;
          /// Returns the amount of links each Uri has.
          /// &lt;/summary&gt;
          public uint ReturnLinkCount(string uri)
          {
              string html;
              Status.Update(uri, false); //this is where the status is called
              try
              {
  
                  html = client.DownloadString(string.Format("http://siteexplorer.search.yahoo.com/search?p=http%3A%2F%2F{0}&amp;fr=sfp&amp;bwm=i", uri));
  
              }
              catch (WebException ex)
              {
                 ProcessError(ex.ToString());
                 return 0;
              }
  
             return (LinkNumber(html));
  
          }
  </code></pre>
  
  <p><strong>Status Classes</strong></p>
  
  <pre><code>public class StatusEventArgs : EventArgs
      {
          private string _message;
          private bool _isidle;
  
          public StatusEventArgs(string message, bool isidle)
          {
              this._message = message;
              this._isidle = isidle;
          }
  
          public bool IsIdle
          {
              get { return _isidle; }
          }
  
          public string Message
          {
              get { return _message; }
          }
      }
  
     public class Status
      {
          public Status()
          {
          }
  
          // Declaring an event, with a custom event arguments class
          public event EventHandler&lt;StatusEventArgs&gt; Sending;
  
          // Some method to fire the event.
          public void Update(string message, bool isIdle)
          {
              StatusEventArgs msg = new StatusEventArgs(message, isIdle);
              OnUpdate(msg);
          }
  
          // The method that invokes the event.
          protected virtual void OnUpdate(StatusEventArgs e)
          {
              EventHandler&lt;StatusEventArgs&gt; handler = Sending;
  
              if (handler != null)
              {
                  handler(this, e);
              }
          }
      }
  </code></pre>
  
  <p><strong>Method That Changes the labels Content</strong></p>
  
  <pre><code> private  void StatusChange(object sender, StatusEventArgs e)
          {
  
              if(!e.IsIdle)
              {
                  lblstatus.Content = e.Message;
                  lblstatus.Foreground = StatusColors.Green;
                  lblstatus.Refresh();
              }
              else
              {
                  lblstatus.Content = e.Message;
                  lblstatus.Foreground = StatusColors.Grey;
                  lblstatus.Refresh();
              }
  
          }
  </code></pre>
  
  <p><strong>The Refresh static method called:</strong></p>
  
  <pre><code> public static class ExtensionMethods
      {
          private static Action EmptyDelegate = delegate() { };
  
          public static void Refresh(this UIElement uiElement)
          {
              uiElement.Dispatcher.Invoke(DispatcherPriority.Render   , EmptyDelegate);
          }
  </code></pre>
  
  <p>Another EDIT: Staring at my code for a bit longer, I've realised, that the foreach loop will execute really quickly, the operation which takes the time, is </p>
  
  <pre><code>yahooResult = yahoo.ReturnLinkCount(modUri); 
  </code></pre>
  
  <p>Therefore I've declared the status class (which handles the event and invokes the label etc) and subscibed to it. I've gotten better results, although it still feels random, sometimes I see a couple of label updates, and sometimes one even though the exact same URI's are passed, so weird.</p>