using System;
using System.Threading;
using System.Data;
using System.Data.SqlClient;

namespace AsyncEx
{
	/// <summary>
	/// Summary description for Class1.
	/// </summary>
	class Class1
	{
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		/// 

		[STAThread]
		static void Main(string[] args)
		{
			string connect_string = GetConnectStringFromConfigFile();
      SqlConnection conn = new SqlConnection(connect_string);
      try
      {
        SqlCommand cmd = new SqlCommand
        ("UPDATE authors SET state='OR' WHERE state='CA'", conn);
        conn.Open();
        // Asynch command execution
        IAsyncResult ar = cmd.BeginExecuteNonQuery();
			// busywait, check every 250 milliseconds
			while (!ar.IsCompleted)
			{
			// do something useful here
			Console.Write(".");
			Thread.Sleep(250);
			}
			// error thrown here if command fails
      int i = cmd.EndExecuteNonQuery(ar);
			// remainder of processing elided
			}
			catch (Exception e) {
				Console.WriteLine(e.Message);
				Console.WriteLine(e.StackTrace);
			}
			finally {
				conn.Close();
			}
		}

    public static void Async1()
    {
      string connect_string = GetConnectStringFromConfigFile();
      connect_string += ";Async=true";
      SqlConnection conn = new SqlConnection(connect_string);
      SqlCommand cmd = new SqlCommand
        ("UPDATE authors SET state='OR' WHERE state='CA'", conn);
      try
      {
        conn.Open();
        // Asynch command execution
        IAsyncResult ar = cmd.BeginExecuteNonQuery();

        while (!ar.IsCompleted)
        {
          Console.Write(".");
          Thread.Sleep(250);
        }

        // retrieve the results (or error) here
        int i = cmd.EndExecuteNonQuery(ar);
        Console.WriteLine("done, {0} rows affected", i);
      }
      catch (Exception e)
      {
        Console.WriteLine(e.Message);
        Console.WriteLine(e.StackTrace);
      }
      finally
      {
        cmd.Dispose();
        conn.Dispose();
      }
    }

		public static void Async2()
		{
			string connect_string = GetConnectStringFromConfigFile();
      connect_string += ";Async=true";
			SqlConnection conn = new SqlConnection(connect_string);
			SqlCommand cmd = new SqlCommand
				("UPDATE authors set state='OR' where state='CA'", conn);
			try
			{
			// Synchronous Open
			conn.Open();
			// Asynch command execution
			IAsyncResult ar = cmd.BeginExecuteNonQuery();
			while (!ar.IsCompleted)
			{
			Console.Write(".");
			Thread.Sleep(250);
			}
			// retrieve the results (or error) here
			int i = cmd.EndExecuteNonQuery(ar);
			Console.WriteLine("done, {0} rows affected", i);
			}
			catch (Exception e) {
			Console.WriteLine(e.Message);
			Console.WriteLine(e.StackTrace);
			}
			finally {
			cmd.Dispose();
			conn.Dispose();
			}
		}

		SqlCommand gcmd = new SqlCommand("select * from authors");

		public void UseEventHandler()
		{
			string connect_string = GetConnectStringFromConfigFile();
      connect_string += ";Async=true";
			SqlConnection conn = new SqlConnection(connect_string);
			gcmd.Connection = conn;
			try
			{

			// Synchronous Open
			conn.Open();
			// Asynch command execution
			gcmd.BeginExecuteReader(
				new AsyncCallback(GetResult),
				null);
			}
			catch (Exception e) {
			Console.WriteLine(e.Message);
			Console.WriteLine(e.StackTrace);
			}
			finally {
			gcmd.Dispose();
			conn.Dispose();
			}
			}
			public void GetResult(IAsyncResult result)
			{
				// harvest results (or error) here
				SqlDataReader rdr = gcmd.EndExecuteReader(result);
				// use results to populate GUI
			}

		public void UseWaitHandles()
		{
      string connect_string1 = GetConnectStringFromConfigFile("server1");
      connect_string1 += ";Async=true";
      string connect_string2 = GetConnectStringFromConfigFile("server2");
      connect_string2 += ";Async=true";
      SqlConnection conn1 = new SqlConnection(connect_string1);
      SqlConnection conn2 = new SqlConnection(connect_string2);

      // execute these simultaneously
      SqlCommand cmd1 = new SqlCommand("SELECT * FROM authors", conn1);
      SqlCommand cmd2 = new SqlCommand("SELECT * FROM titles", conn2);

			WaitHandle[] handles = new WaitHandle[2];
			try
			{
			conn1.Open();
      conn2.Open();

			IAsyncResult ar1 = cmd1.BeginExecuteReader(null, null);
			IAsyncResult ar2 = cmd1.BeginExecuteReader(null, null);
			handles[0] = ar1.AsyncWaitHandle;
			handles[1] = ar2.AsyncWaitHandle;

			// wait for both commands to complete
			WaitHandle.WaitAll(handles);
			SqlDataReader rdr1 = cmd1.EndExecuteReader(ar1);
			SqlDataReader rdr2 = cmd2.EndExecuteReader(ar2);
			// process both readers
			// ...
			rdr1.Close(); rdr2.Close();
			}
			catch (Exception e) 
			{
				Console.WriteLine(e.Message);
				Console.WriteLine(e.StackTrace);
			}
			finally 
			{
				cmd1.Dispose();
				cmd2.Dispose();
				conn1.Dispose();
        conn2.Dispose();
			}
		}
    public static string GetConnectStringFromConfigFile()
    {
      return "server=.;integrated security=sspi;database=pubs";
    }

    public static string GetConnectStringFromConfigFile(string svrname)
    {
      return "server=" + svrname + ";integrated security=sspi;database=pubs";
    }
	}
}
