2017-02-14 3 views
0

参照を持つクラスから別のメソッドを呼び出すメソッドがあり、そのメソッドはデータテーブルを返します。C#参照付きのスレッドからデータテーブルを返す

スレッド内でクエリを実行しようとしていますが、スレッド内でクエリ自体を実行するのは簡単ですが、スレッドからデータテーブルを返すにはどうすればよいですか?クラスを呼び出すメソッドの

例:

private void loadCombo(string sqlComand, string value, ComboBox loadBox) 
     {   
      DataTable dt = new DataTable(); 

      //Thread thread = new Thread(() => sqlScript.loadCombo(sqlComand, value, loadBox)); 
      //thread.start(); 

      dt = sqlScript.loadCombo(sqlComand, value, loadBox); 
      loadBox.ValueMember = value; 
      loadBox.DataSource = dt; 
      loadBox.Refresh(); 
     } 
+0

は、Webまたはクライアント・アプリケーションで作業していますか? –

+0

Windowsフォームクライアントアプリケーション。上記の例のようにクラスを正常に呼び出すと機能します。私は、スレッドでこれらを実行し、マルチスレッドを実装できれば、アプリケーションをより高速にすることができると考えています。私はこれらのタイプのクエリを実行しているので。 – shinga77

+0

別のスレッドから 'loadBox'を設定しようとすると、エラーが発生するはずです。エラー[次回]を検索しようとします(http://stackoverflow.com/q/2562946/1997232)。 – Sinatr

答えて

0

別のスレッドでデータベースクエリを実行する代わりに、async-awaitアプローチを使用します。これは、1つのスレッドで実行され、UIをブロックしません。

public class SqlScript 
{ 
    public async Task<DataTable> LoadDataAsync(string command, object value) 
    { 
     // Load data asynchronously by using ..Async methods 
    } 
} 

private async Task loadComboAsync(string sqlComand, string value, ComboBox loadBox) 
{   
    var data = await sqlScript.LoadDataAsync(sqlComand, value); 

    loadBox.ValueMember = columnNameWhichRepresentValue; 
    loadBox.DataSource = data; 
} 

を設定するあなたは、「データの照会」の操作を分離する必要があり、これとComboBoxのために

そして、あなたはとにかくそれを行います新しいデータソースを設定し、loadBox.Refreshメソッドを呼び出す必要はありません。

Task.Runを使用しないでください。データベース操作は、他のスレッドで実行する必要がある「重い」ものは何もしません。データベース操作はコマンドを送信して応答を待つだけなので、待機のために別のスレッドを使うことはリソースの無駄です。
は、代わりにSqlConnection.OpenAsyncSqlCommand.ExecuteReaderAsync方法

public async Task<DataTable> loadCombo(string sqlCommand, string value) 
{ 
    var yourConnectionString = "DataSource=..."; 
    using (var connection = new SqlConnection(yourConnectionString)) 
    using (var command = new SqlCommand(sqlCommand, connection)) 
    { 
     await connection.OpenAsync(); 
     var reader = await command.ExecuteReaderAsync(); 

     var data = new DataTable(); 
     data.Load(reader); 
     return data; 
    } 
} 
-1

これは単純な質問のように聞こえます。

あなたはTask使用することができます(同様にasync/awaitを、それは通常、複数実行を防ぐために、ボタンに対応する有効/無効にするために使用されます、オプションであるかもしれない)UIをブロックせずにイベントハンドラで、長時間実行されるコードを実行します。あなたはまだUI要素にアセスを起動する必要があります。

async void loadCombo(string sqlComand, string value, ComboBox loadBox) 
{ 
    // disable button 

    await Task.Run(() => 
    { 
     var dt = sqlScript.loadCombo(sqlComand, value, loadBox); 
     Invoke((Action)(() => 
     { 
      loadBox.ValueMember = value; // is it out parameter? anyway, copying your code 
      loadBox.DataSource = dt; 
      loadBox.Refresh(); 
     })); 
    } 

    // enable button 
} 

別のスレッドからDataTableを作成し、合格するために何の問題があるべきではありません。

+0

'Task.Run'はThreadPoolの別のスレッドを使用します。これはスレッドの無駄になります。代わりに 'Sql ... Async'メソッドを使用して、データを実際の非同期の方法でロードしてください。 – Fabio

+0

@Fabio、そうです。私は、長い実行同期メソッド( 'sqlScript'が何であるかの手がかりなし)のために、待っている/呼び出す詳細に関して答えることができました。 – Sinatr

+0

sqlScriptは、sqlScriptというクラスへの参照です。 loadComboは、そのクラス内のメソッドです。 – shinga77

-1

を使用し、あなたに@Sinatrをありがとう、私はちょうどあなたの答えビットをtwekしなければならなかった、以下のコードは動作するようです。

private async void loadCombo(string sqlCommand, string value, ComboBox loadBox) 
     { 
      await Task.Run(() => 
      { 
       var dt = sqlScript.loadCombo(sqlCommand, value, loadBox); 
       Invoke((Action)(() => 
       { 
        loadBox.ValueMember = value; 
        loadBox.DataSource = dt; 
       })); 
      }); 
     } 
-1

は@Sinatrと@Fabioが、私はあなたの答えの組み合わせをテストし、以下の私の最速復帰時間を与えるようで、ありがとうございます。

メインフォームのメソッドコール:

private async Task loadCombo(string sqlCommand, string value, ComboBox loadBox) 
     { 
      var data = await sqlScript.loadCombo(sqlCommand, value); 
      loadBox.ValueMember = value; 
      loadBox.DataSource = data; 
     } 

sqlScriptクラスメソッド:

public async Task<DataTable> loadCombo(string sqlCommand, string value) 
     { 
      SqlConnection myConn; 
      SqlCommand myCmd = default(SqlCommand); 
      SqlDataReader oResult; 
      DataTable dt = new DataTable(); 

      await Task.Run(() => 
      { 

       using (myConn = new SqlConnection("Data Source=" + frmMain.sqlServer + ";" + "Initial Catalog=" + frmMain.sqlData + ";User Id=" + frmMain.sqlUser + ";Password=" + frmMain.sqlPwd + ";")) 
       { 
        try 
        { 
         myConn.Open(); 

         if (myConn.State == ConnectionState.Open) 
         { 
          myCmd = new SqlCommand((sqlCommand), myConn); 
          oResult = myCmd.ExecuteReader(); 
          dt.Load(oResult); 
          myConn.Close(); 
         } 
         else 
         { 

         } 
        } 
        catch (Exception err) 
        { 
         using (StreamWriter w = File.AppendText("ErrorLog.log")) 
         { 
          frmMain.Log("sqlScripts.loadCombo: " + err.Message, w); 
         } 
        }//End Try 
       }//End using 
      }); 
      return dt; 
     } 
関連する問題