1

現在、順番に実行する必要があるいくつかのクエリがあります (いくつかは、後のクエリで取得する一時テーブルを作成します)。

クエリはBackgroundWorkerスレッドで実行されます。現在、クエリがある場合は、CancellationPendingクエリ呼び出しの間にメソッドから抜け出します。

ただし、このアプローチには問題があります。単一のクエリが長時間実行されたり、返されなかったりする場合があるため、ポーリング中に各クエリを実行できる必要がありますBackgroundWorker.CancellationPending

この場合に使用するのに最適な非同期パターンは何ですか? 各クエリに入力する必要がありDataTableますが、時間がかかりすぎる場合はキャンセルできます。

4

2 に答える 2

1

編集:私にとってうまくいった解決策は、非同期ADO.NETメソッドを使用することでした。BeginExecute...EndExecute...

BackgroundWorkerがキャンセルを要求したかどうかを確認しながらクエリを非同期に実行するコードのスニペットを次に示します。この関数は、クエリが最後まで実行された場合は true を返し、キャンセルが実行された場合は false を返します。

BackgroundWorkerコードはのDoWork関数内のどこかから呼び出す必要があります。

SqlCommand command = new SqlCommand(query, connectionObj);
IAsyncResult result = command.BeginExecuteReader();  // end async execution

// check for user cancellation while result is not complete
while (!result.IsCompleted)
{
    if (myBackgroundWorker.CancellationPending)
    {
        command.Cancel();  // cancel the existing command
        try
        {
             command.EndExecuteReader(result);  // cancel async execution
        }
        catch (SqlException e)
        {
            // will always enter here due to command.Cancel()
            // this is expected
        }

        return false;
    }

    Thread.Sleep(100);  // sleep so loop doesn't consume all the resources
}

// result is complete, do something with data
using (SqlDataReader reader = command.EndExecuteReader(result))
{
    DataTable table = new DataTable();
    table.Load(reader);
}

// do something with table
return true;
于 2013-01-22T19:56:33.970 に答える
1

いずれの場合も、協調的に中止してください。の使用についても考えないでくださいThread.Abort

偉大な Stephen Toub がベスト プラクティスを書きました。

TL;DR: タイムアウト タイマーが作動すると、Taskすぐに完了し、SQL クエリを実行し続けます。あなたはただそれを無視します。

于 2013-01-21T22:39:23.660 に答える