title: How to Deal with Asynchronous SQL Queries from Non-UI Threads
body: <p>All, I have successfully used ADO.NET to make use of asynchronous SQL queries similar to the example below. In the example shown the method ExecNonQuery is being invoked from the UI thread. This works well, but I wondered how I would handle the callback if I were to call ExecNonQuery from a non-UI thread? </p>
  
  <p>Note. Clearly, in such a case I would amend ExecNonQuery, so that such things as <code>this.toolStripStatusLabel1.Text</code> were dealt with accordingly, or removed.</p>
  
  <pre><code>public bool ExecNonQuery(string strCmd, string strUserMsg = "")
  {
      try
      {
          SqlCommand cmd = new SqlCommand();
          cmd.Connection = conn;
          cmd.CommandText = strCmd;
          cmd.CommandTimeout = 0;
          bIsExecuting = true;
          AsyncCallback callback = new AsyncCallback(HandleCallback);
          cmd.BeginExecuteNonQuery(callback, cmd); 
          return true;
      }
      catch (Exception Ex)
      {
          bIsExecuting = false;
          this.toolStripStatusLabel1.Text = String.Format("Ready (last error: {0})", Ex.Message);
          if (conn != null)
              conn.Close();
      }
      return false;
  }
  
  private delegate void DisplayInfoDelegate(string Text);
  
  private void HandleCallback(IAsyncResult result)
  {
      try
      {
          // Retrieve the original command object, passed
          // to this procedure in the AsyncState property
          // of the IAsyncResult parameter.
  
          SqlCommand command = (SqlCommand)result.AsyncState;
          int rowCount = command.EndExecuteNonQuery(result);
          string rowText = " rows affected.";
          if (rowCount == 1)
              rowText = " row affected.";
          rowText = rowCount + rowText;
  
          // Call the procedure from the form's thread.
          DisplayInfoDelegate del = new DisplayInfoDelegate(DisplayResults);
          this.Invoke(del, rowText);
      }
      catch (Exception ex)
      {
          // Because you are now running code in a separate thread, 
          // if you do not handle the exception here, none of your other
          // code catches the exception.
  
          // You can create the delegate instance as you 
          // invoke it, like this:
          this.Invoke(new DisplayInfoDelegate(DisplayResults), 
              String.Format("Ready(last error: {0}", ex.Message));
      }
      finally
      {
          bIsExecuting = false;
          if (conn != null)
              conn.Close();
      }
  }
  
  private void DisplayResults(string Text)
  {
      this.toolStripStatusLabel1.Text = Text;
      this.toolStripProgressBar1.Style = ProgressBarStyle.Blocks;
      this.toolStripProgressBar1.Value = 100;
  }
  </code></pre>
  
  <p>Thanks for you time.</p>