6

ASP.NET 4.5 を使用して、新しい async/await おもちゃで遊んでいます。ベンダー固有のリーダー (SqlDatareader など) をラップする IDataReader 実装クラスがあります。次のように同期的に動作する単純な ExecuteSql() メソッドがあります。

public IDataReader ReaderForSql(string sql)
{
    var cmd = NewCommand(sql, CommandType.Text);
    return DBReader.ReaderFactory(cmd.ExecuteReader());
}

私が欲しいのは、これの非同期バージョンです。これが私の最初の試みです:

public Task<IDataReader> ReaderForSqlAsync(string sql, CancellationToken ct)
{
    var cmd = NewCommand(sql, CommandType.Text);
    return cmd.ExecuteReaderAsync(ct)
              .ContinueWith(t => DBReader.ReaderFactory(t.Result));
}

そして私はそれを使用します:

using (var r = await connection.ReaderForSqlAsync("SELECT ...", cancellationToken))
{
    ...
}

これは、これまでの限られたテストではうまく機能します。しかし、この Cloud9 ビデオを数回見た後: http://channel9.msdn.com/Events/aspConf/aspConf/Async-in-ASP-NETに関する警告について心配になりました。

  • 追加のスレッドプール リソースを消費して続行 - Readerfactory は非常に軽量です。
  • Task.Result ブロッキング

ContinuationToken を ExecuteReaderAsync() に渡しているので、キャンセルは ExecuteReaderAsync() が失敗する可能性があるもう 1 つの理由のようです (結局のところ SQL です!)

ContinueWith を実行しようとすると、タスクの状態はどうなりますか? t.Result はブロックしますか? 投げる?間違ったことをしますか?

4

2 に答える 2

5

ContinueWithはデフォルトで現在のタスク スケジューラ (スレッド プール スレッド) を使用しますがTaskContinuationOptions.ExecuteSynchronously、明示的な とを渡すことで変更できますTaskScheduler

そうは言っても、私はこれを最初の努力として行います:

public async Task<IDataReader> ReaderForSqlAsync(string sql, CancellationToken ct)
{
  var cmd = NewCommand(sql, CommandType.Text);
  var readerResult = await cmd.ExecuteReaderAsync(ct).ConfigureAwait(false);
  return DBReader.ReaderFactory(readerResult);
}

asyncawaitすべてのContinueWith珍味とエッジの状態を一貫した方法で処理します。パフォーマンス テストで重大な問題であることが示された場合、このコードを複雑にして高速化できる可能性があります。

于 2012-11-30T20:06:46.393 に答える
2

Resultタスクが完了していない場合はブロックします。しかし、継続ハンドラーには既にあります。だからブロックしない。あなたは正しいことをしています。

Result失敗したタスクで呼び出すと (そして、これが発生する可能性があると言います)、例外が再スローされます。これにより、同じ例外で継続が失敗し、返された最終タスクReaderForSqlAsyncも失敗します。これは良いことです: 一連のタスク全体に障害が発生し、すべての例外が観察されました (飲み込まれたのとは対照的です)。したがって、これもベストプラクティスです。

コンピューティング バウンドの作業にスレッドを使用することは常に問題ありません。繰り返しますが、ContinueWith を使用して正しいことを行っています。結局のところ、IDataReader どこかを計算する必要があります。計算できません。

于 2012-11-30T19:39:17.720 に答える