2016-08-04 13 views
1

私はデータセットテーブルにバルク挿入するためのかなりのデータテーブルを持っています 大きなサイズのため、1つのテーブルは挿入を完了するのに5分かかりました。 2つのテーブルは、私は今、一括挿入のための非同期操作を行うにしようとしていますが、任意のデータが挿入されていないにも私にエラーを与えてもされていない私に10分バルクコピーのための非同期

static void Main(string[] args) 
{ 
    DataTableBulkInsert(DataTable1); 
    DataTableBulkInsert(DataTable2); 
} 

public static void DataTableBulkInsert(DataTable Table){ 
    SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(myConnection); 
    sqlBulkCopy.DestinationTableName = "dbo.DatabaseTable"; 
    myConnection.Open();      
    sqlBulkCopy.WriteToServer(Table); 
    myConnection.Close(); 
} 

を取りました。例外をキャプチャする方法は?

static void Main(string[] args) 
{ 
    var insert1 = Task.Run(async() => await DataTableBulkInsert(DataTable1); 
    var insert2 = Task.Run(async() => await DataTableBulkInsert(DataTable2); 
    Task.WhenAll(insert1, insert 2); 
} 

public static async Task<Boolean> DataTableBulkInsert(DataTable Table) 
{ 
     try 
     { 
      SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(myConnection); 
      sqlBulkCopy.DestinationTableName = "dbo.DatabaseTable"; 
      myConnection.Open();      
      await sqlBulkCopy.WriteToServerAsync(Table); 
      myConnection.Close(); 
     } 
     catch (Exception (e)) 
     { 
     console.write(e); 
     } 
     return true; 
} 
+0

'console.write(e);'行にデバッガを設定しようとしましたか?私の経験では、非同期メソッドはしばしば例外を取り除きます。 – smoksnes

+3

'Task.WaitAll(insert1、insert 2)を使う' –

答えて

3

Task.Runは、ここでは何も役立たないものです。また、メソッドの2回の実行の間に、単一の接続オブジェクトを共有しようとしないでください。ような何か:通常

static void Main(string[] args) 
{ 
    var insert1 = DataTableBulkInsert(DataTable1); 
    var insert2 = DataTableBulkInsert(DataTable2); 
    Task.WaitAll(insert1, insert2); 
} 

public static async Task DataTableBulkInsert(DataTable Table) 
{ 
     using(var localConnection = new SqlConnection(/* connection string */)) 
     { 
      SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(localConnection); 
      sqlBulkCopy.DestinationTableName = "dbo.DatabaseTable"; 
      localConnection.Open();      
      await sqlBulkCopy.WriteToServerAsync(Table); 
     } 
} 

return awaitはアンチパターンですが、ここであなたはusing文が一括読み込みが完了するまで、あなたの接続を閉じないようにそれを使用したいと思います。

はまた、私はTask.WhenAllを使用するよりも慣用され、その後すぐにWaitを呼び出すTask.WaitAllた実際待機を、使用してに切り替え。

+0

_return awaitは反パターン_です - 非常に面白いです。これに関するさらに詳しい情報を提供できますか? – smoksnes

+1

@smoksnes - 'await'は、他のコードが終了してから現在のメソッドを一時停止する方法です。あなたの方法が再開されたときにやるべきことがすべて「私は終わった」と言うなら、なぜあなたはすべての努力に行きましたか?つまり、実際のアンチパターンは、メソッド内で(それがここにあるように) '唯一*'待っていて、 'finally'または'を使用して 'try'ブロック内にない場合は' return await'です'ブロック(この場合、' return'の後に実行する追加のコードがあります) –

+1

@smoksnes - コンパイラを求める[github issue](https://github.com/dotnet/roslyn/issues/1981)さえありますそれを最適化する。 –

0

Task.WhenAllを待つする必要があるタスクオブジェクトまたはその通常の実行を継続し、メインメソッドが直ちに終了し、次のコードを返します。

これはコンソールアプリケーションで、メインはasyncとしてマークすることはできませんので、あなたは、この使用することができます。

Task.WhenAll(insert1, insert2).Wait(); // wait for the returned Task object to Complete 

を通常の使用である:await (Task.WhenAll(...))いますが、async方法として主にマークを付けることはできません。

+0

.Wait();を追加した後で動作します。 しかし、今私は接続を開け閉めている問題が発生しています。複数のバルクコピーに対して1つの接続を許可する方法は? – Jonathan

+0

ちょうど試してみました。 – Jonathan

+0

@ジョナサンあなたは、タスクごとに別々の接続を作成する必要があるかもしれません。 'Task.WhenAll(insert1、insert2).Wait();'コード行の後に接続を閉じることができます。 – user3185569

関連する問題