title: Self-updating App with App Domain on Different Thread
body: <p>I've been working to get a windows service to automatically restart an app when there is a new version. My code is below, and it actually works. My question is this: Is there a big no-no in here somewhere? I'm new to creating app domains on separate threads, and I'd like to know if there is a more elegant way to accomplish this. I'm also concerned that maybe I have a big blind spot regarding how I'm handling this. Any advice is appreciated.</p>
  
  <p>There are two general pieces: the Windows service that runs, starts my app in a different process, then polls to detect when a new version of that app is available. The second piece is the actual app that gets started, updated, restarted.</p>
  
  <p>First, when the service starts, it calls LoadApp() so that the app starts running.    </p>
  
  <pre><code>private void LoadApp()
      {
      // ** appDomainSetup here **
  
      this._appDomain = AppDomain.CreateDomain("MyUpdatedApp", AppDomain.CurrentDomain.Evidence, appDomainSetup);
  
      this._tokenSource = new CancellationTokenSource();
  
      Task.Factory.StartNew(() =&gt;
      {
          try
          {
              this._appDomain.ExecuteAssembly(assembly);
          }
          catch (AppDomainUnloadedException ex)
          {
              Debug.WriteLine(ex.ToString());
          }
      }, _tokenSource.Token);
  }
  </code></pre>
  
  <p>Then, every 10 seconds, the timer calls this method:</p>
  
  <pre><code>private void Process(object stateInfo)
  {
      if (!Monitor.TryEnter(_locker)) { return; }
  
      try
      {
          // Check for new binaries. If new, copy the files and restart the app domain.            
          if (!NewAppVersionReady()) { return; }
          DeleteFiles();
          CopyFiles();
          RestartAppDomain();
      }
      finally
      {
          Monitor.Exit(_locker);
      }
  }
  </code></pre>
  
  <p>RestartAppDomain() looks like this. Note that I get an exception when I unload the app domain on the second line in this method. (I get around that by catching the exception and basically ignoring it.)</p>
  
  <pre><code>private void RestartAppDomain()
  {
      this._tokenSource.Cancel();
      AppDomain.Unload(this._appDomain);
      LoadApp();
  }
  </code></pre>
  
  <p>Edit: I've since found out that the AppDomain.Unload() line is unnecessary. Without it, the service still updates the app with a new version and then starts the new version of the app. My big concern is calling Cancel() on the token source. I'd like the app to be able to shut down gracefully instead of just forcing it shut.</p>