title: How to open a WPF window from an async method
body: <p>I've been trying to find a solution for this, but at this point nothing that I've found has made the click. I'm starting with WPF, so I may just missed some obvious answer, but I would highly appreciate an answer for dumbs. This is the situation:</p>
  
  <p>My app is structured using MVVM. Its main functionality is called from a button. Once called, it will loop through all the files within an specified directory and perform some renaming. While doing this loop, I wanted to show a progress bar indicated how many files have been renamed out of the total.
  The progress value is a property binded to the <em>Progressbar</em> control</p>
  
  <p>I've only been able to update the progress bar asynchronously; otherwise it will remain empty until the process finishes. Right now its working with a <em>BackgroundWorker</em>.</p>
  
  <pre><code>_bgWorker.DoWork += (s, e) =&gt;
  {
      RenamingMethod();
  };
  ...
  RenamingMethodCommand = new RelayCommand(_ =&gt;_bgWorker.RunWorkerAsync());
  </code></pre>
  
  <p>For performing the renaming, a hash is expected in the name of the file. This hash will be translated to a user-entered value if found, otherwise a window should be displayed asking the user to enter it.</p>
  
  <p>This window is not being able to be displayed in a <em>MTAThread</em> (I'm using <em>ShowDialog</em>, I haven't found any other way to make it appear), and so I can't call it from the async methods in my main window. The only way I found to make it work was calling everything inside <em>RenamingMethod</em> like this:</p>
  
  <pre><code>public void RenamingMethod()
  {
      Application.Current.Dispatcher.Invoke((Action)delegate
      {
          //code for renaming
      }
  }
  </code></pre>
  
  <p>At this point, the progress bar is only updated the moment I close the pop up window. Then it remains on the same value until a new window is opened and closed.</p>
  
  <p>I would like to open the pop up window from the asynchronous method that updates the progress bar, so the evolution of this is smooth, and its stopped when a new window is openned. Or being able to update the progress bar synchronously would probably work as well.</p>
  
  <p>Here's the code in more detail:</p>
  
  <pre><code>public void RenameMethod()
  {
      Application.Current.Dispatcher.Invoke((Action)delegate
      {
          IEnumerable&lt;string&gt; files = Directory.EnumerateFiles(
              OriginMediaFolder, 
              "*.*",
              SearchOption.AllDirectories).
          Where(name =&gt; name.EndsWith(".jpg") || name.EndsWith(".mp4"));
  
          int numberOfFiles = files.Count();
          float fileNumber = 0;
          foreach (string file in files)
          {
              MoveAndRenameFile(file);
              ProgressValue = (int)(100 * (fileNumber++ / numberOfFiles));
          }
      });
  }
  
  public void MoveAndRenameFile(string file)
  {
      //Name structure: path/1234567891234567-hash.ext
      string fileName = Regex.Match(file, @"[^\/\\]+\.",RegexOptions.RightToLeft).
          Value.TrimEnd('.');
      string date = fileName.Substring(0, 16);
      string hash = fileName.Substring(17);
      if (!HashToName(hash, out string gameName))
      {
          var gameNamingWindow = GetNewNameFromUser(hash);
      }
      string extension = Regex.Match(file, @"\..+\Z", RegexOptions.RightToLeft).Value;
  
      if (!Directory.Exists(DestinationMediaFolder + "/" + gameName))
          Directory.CreateDirectory(DestinationMediaFolder + "/" + gameName);
  
      File.Move(file, DestinationMediaFolder + "/" + gameName + "/" + date + extension);
  }
  
  public string GetNewNameFromUser(string hash)
  {
      var gameNamingWindow = new NewGameWindow.MainWindow(OriginMediaFolder, hash);
      if (gameNamingWindow.ShowDialog().Value)
      {
          string gameName = gameNamingWindow.Result;
          NameHashes.Add(new NameHash
          {
              GameName = gameName,
              Hash = hash
          });
          return gameName;
      }
      return hash;
  }
  </code></pre>