2

最近、このトピックについてよく読んでいますが、まだ何かを明確にする必要があります

非同期メソッドの全体的なアイデアはスレッドエコノミーです:

多くのタスクを少数のスレッドで実行できるようにします。これは、ハードウェア ドライバーを使用してジョブを実行し、スレッドをスレッド プールに解放して他のジョブを処理できるようにすることによって行われます。

注意してください。

別のスレッドを結び付ける非同期デリゲートについて話しているのではありません(呼び出し元と並行してタスクを実行します)。

ただし、非同期メソッドの例の 2 つの主なタイプを見てきました。

  • たとえば 、既存のI/O 非同期操作のみを使用するコード サンプル (本から) 。また、既存の.net I/O 操作を使用しない非同期メソッド のサンプル も見つかりませんでし た。beginXXX / endXXStream.BeginRead
    Stream.BeginRead

  • このようなコード サンプル (およびこの)。これは実際には非同期操作を呼び出していません (作成者は自分がそうであると考えていますが、実際にはスレッドをブロックさせています!)

質問 :

非同期メソッド は、.net I/O のような既存のメソッドでのみ使用されBeginXXX , EndXXXますか?

つまり、 のような独自の非同期メソッドを作成したい場合 BeginMyDelay(int ms,...){..} , EndMyDelay(...)。ブロックされたスレッドを結び付けないとできませんでした....正しいですか?

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

ps この質問は、.net4.5 ではなく .net 4 としてタグ付けされていることに注意してください。

4

3 に答える 3

1

あなたはAPMについて話している。APM は、IO Completion ポートとして知られる OS の概念を広く使用しています。そのため、さまざまな IO 操作が APM を使用するのに最適な候補です。

独自の APM メソッドを作成できます。しかし、実際には、これらのメソッドは既存の APM メソッドを超えるか、IO バウンドになり、ネイティブ OS メカニズム (FilesStreamオーバーラップ ファイル IO を使用する など) を使用します。

コンピューティングにバインドされた非同期操作の場合、APM のみが複雑さを増加させます (IMO)。

もう少し明確にします。

ハードウェアでの作業は、その性質上非同期です。ハードウェアはリクエストを実行する時間を必要とします - newtork カードはデータを送信または受信する必要があり、HDD は読み取り/書き込みを行う必要があります。IO が同期の場合、IO リクエストを生成したスレッドは応答を待っています。ここで APM が役に立ちます。待つ必要はありません。別のことを実行してください。IO が完了したら、電話します、と APM は言います。

要点 - 操作は CPU の外部で実行されます。

IO なしで実行に CPU を使用するコンピューティング バウンド操作を作成している場合、ここで待機する必要はありません。したがって、APM は役に立ちません。CPU が必要な場合はスレッドが必要です。スレッド プールが必要です。

于 2013-03-23T09:52:49.217 に答える
0

独自の非同期メソッドを作成できると思いますが、よくわかりません。たとえば、新しいスレッドを作成し、それが何らかの作業 (db クエリなど) を完了するのを待ちます。

システム全体のパフォーマンスに関しては、別のスレッドを作成するだけだと言うので、おそらく役に立ちません。ただし、たとえば IIS で作業している場合、「バックグラウンド」操作を待っている間、元の要求スレッドを他の要求に使用できます。

IIS は固定数のスレッド (スレッド プール) を持っていると思いますので、このような場合に役立ちます。

于 2013-03-23T10:09:34.237 に答える
0

つまり、 BeginMyDelay(int ms,...){..} 、 EndMyDelay(...) のような独自の非同期メソッドを作成したい場合。ブロックされたスレッドを結び付けないとできませんでした....正しいですか?

私は非同期の実装を掘り下げていませんが、これができない理由はわかりません。

最も簡単な方法は、[タイマーなど] またはある種のイベント システム IIRC を支援する既存のライブラリを使用することです。

ただし、ライブラリ ヘルパーを使用したくない場合でも、「ブロックされたスレッド」という問題が発生します。

確かに、コードは次のようになります。

while (true){
      foreach (var item in WaitingTasks)
              if (item.Ready())
                 /*fire item, and remove it from tasks*/;

      /*Some blocking action*/
}

つまり、「何らかのブロッキング アクション」は「ブロッキング」である必要はありません。スレッドを生成/スリープするか、それを使用して一部のデータを処理できます。たとえば、Unity ゲーム エンジンは、コルーチンでも同様のことを行います。ここでは、すべてのコードを処理する同じスレッドが、さまざまなコルーチン (時間のために遅延している) を更新する必要があるかどうかもチェックします。/*いくつかのブロッキング アクション*/を ProcessGameLoop() に置き換えます。

お役に立てば幸いです。お気軽に質問や投稿の修正などをお寄せください。

于 2013-03-23T10:53:42.110 に答える