title: WPF Using Multiple Threads to Display Loading Message
body: <p>I've posted a similar question before, however now I am tailoring this question to a specific approach that I have decided to go with.</p>
  
  <p>Simply put what I am trying to do is display a loading message after the user clicks on one page, that dissapears when the next page is fully loaded (loading 27000 companies into a DataGrid) and then the next page is displayed. The order looks like this;</p>
  
  <ol>
  <li>User clicks on button on first page</li>
  <li>"Please Wait...." is displayed on the same page whilst the next page
  is loading</li>
  <li>Next page is fully loaded</li>
  <li>Hide "Please Wait...."</li>
  <li>Display next page</li>
  </ol>
  
  <p>What was recommended to me was using <code>async</code> and <code>wait</code>. This however froze my UI and would not work (<code>Additional information: The calling thread cannot access this object because a different thread owns it.</code>). I then started looking at using multiple threads which can hopefully solve my problem. This is what I have attempted so far;</p>
  
  <p><strong>The user has clicked the button to the next page</strong></p>
  
  <pre><code>public CompanyManagement()
      {
          InitializeComponent();
          Thread thread = Thread.CurrentThread;
          this.DataContext = new
          {
              ThreadId = thread.ManagedThreadId
          };
      }
  </code></pre>
  
  <p><strong>The Page's Loaded event is called;</strong></p>
  
  <pre><code>    private void PageLoaded(object sender, RoutedEventArgs e)
      {          
          Thread thread = new Thread(() =&gt;
          {
              var wait = new PleaseWait("My title", "My Message", () =&gt; FillDataGrid());
              wait.ShowDialog();
              System.Windows.Threading.Dispatcher.Run();
          });
  
          thread.SetApartmentState(ApartmentState.STA);
          thread.Start();
      }
  </code></pre>
  
  <p><strong>FillDataGrid() is the method that takes all the time (retrieves the companies over OleDB), and looks like this;</strong></p>
  
  <pre><code>private void FillDataGrid()
      {
          var _cDS = new CompanyDataService();
          var Companies = new ObservableCollection&lt;CompanyModel&gt;();
          Companies = _cDS.HandleCompanySelect();
          CompanyICollectionView = CollectionViewSource.GetDefaultView(Companies);
          //CompanyICollectionView.SortDescriptions.Add(new SortDescription("CompanyName", ListSortDirection.Ascending));
          DataContext = this;
          cancelButton.Visibility = Visibility.Hidden;
  
          if (compNameRad.IsChecked == false &amp;&amp; 
              compTownRad.IsChecked == false &amp;&amp; 
              compPcodeRad.IsChecked == false)
          {
              searchBox.IsEnabled = false;
          }
          dataGrid.SelectedIndex = 0;
          SetDefaultFilter();
      }
  </code></pre>
  
  <p>This almost works in that the next page is loaded, the "Please Wait...." is displayed however I then get the error: The calling thread cannot access this object because a different thread owns it. Am I using the thread functionality incorrectly?</p>
  
  <p><strong>EDIT</strong>: I should show <code>PleaseWait</code> too!</p>
  
  <pre><code>    public partial class PleaseWait : Window
      {
          readonly Action _action;
          public PleaseWait(string title, string message, Action action)
          {
              _action = action;
              InitializeComponent();
              this.Title = title;
              this.label.Content = message;
          }
  
          private async void loaded(object sender, RoutedEventArgs e)
          {
              await Task.Run(() =&gt; _action());
              this.Close();
          }
      }
  </code></pre>
  
  <p><strong>EDIT</strong>: For StepUp;</p>
  
  <pre><code>    private void PageLoaded(object sender, RoutedEventArgs e)
      {
          Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =&gt;
          {
              var wait = new PleaseWait("My title", "My Message", () =&gt; FillDataGrid());
              wait.ShowDialog();
              Dispatcher.Run();
          }));
      }
  </code></pre>