2011-10-25 15 views
1

すべて、以下の例のような非同期SQLクエリを使用するためにADO.NETを使用するのに成功しました。示された例では、メソッドExecNonQueryがUIスレッドから呼び出されています。これはうまくいきますが、UI以外のスレッドからExecNonQueryを呼び出す場合、コールバックをどのように処理するのだろうと思いましたか?非UIスレッドから非同期SQLクエリを処理する方法

注。明らかに、そのような場合、私はExecNonQueryを修正して、this.toolStripStatusLabel1.Textのようなものがそれに応じて処理されるか削除されるようにしました。

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; 
} 

ありがとうございました。

+0

私の頭に浮かぶのは、並行処理の例外を使用することです。レコードが最後に更新された日時を示すタイムスタンプタイプのフィールドをデータベースに作成できます。タイムスタンプがデータベース内のタイムスタンプと競合すると、同時実行エラーがスローされます。 –

+0

「SynchronizationContext」とは何ですか?(ASP、WinForms、WPFなど)を使用しているUIフレームワークは何ですか – SliverNinja

+0

謝罪。これはWinFormsで行われています。 – MoonKnight

答えて

1

コールバックには違いがありません。ExecNonQuery - HandleCallbackのスレッドは、スレッドプールスレッド上で実行されます。

変更が必要な場合があります。UIスレッドで実行されていない場合は、ExecNonQueryで直接UIコントロールにアクセスしないでください。

ニック

関連する問題