私は見ていましたこの質問、作成する方法を探していますシングルスレッド.NET のイベントベースの非ブロッキング非同期 Web サーバー。
この答えコード本体が単一のスレッドで実行されると主張し、当初は有望に見えました。
ただし、私はこれを C# でテストしました:
using System;
using System.IO;
using System.Threading;
class Program
{
static void Main()
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
var sc = new SynchronizationContext();
SynchronizationContext.SetSynchronizationContext(sc);
{
var path = Environment.ExpandEnvironmentVariables(
@"%SystemRoot%\Notepad.exe");
var fs = new FileStream(path, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite, 1024 * 4, true);
var bytes = new byte[1024];
fs.BeginRead(bytes, 0, bytes.Length, ar =>
{
sc.Post(dummy =>
{
var res = fs.EndRead(ar);
// Are we in the same thread?
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}, null);
}, null);
}
Thread.Sleep(100);
}
}
そして結果は次の通りでした:
1
5
答えとは逆に、読み取りを開始するスレッドと読み取りを終了するスレッドはない同じ。
それで私の質問は、どうやってシングルスレッド.NET のイベントベースの非ブロッキング非同期 Web サーバー?
ベストアンサー1
全体的にはSetSynchronizationContext
誤解を招く内容ですが、これは単にマーシャリングのメカニズムであり、作業は依然として IO スレッド プールで実行されます。
あなたが求めているのは、キューと収穫の方法だ非同期プロシージャ呼び出しメインスレッドからのすべてのIO作業に使用されます。多くの高レベルフレームワークがこの種の機能をラップしており、最も有名なものはリベント。
さまざまなオプションについての優れた要約がここにあります:epoll、poll、threadpool の違いは何ですか?。
.NET では、メソッドを呼び出すときに IO アクセスを処理する特別な「IO スレッド プール」が用意されており、スケーリングがBeginXYZ
すでに行われています。この IO スレッド プールには、ボックス上のプロセッサごとに少なくとも 1 つのスレッドが必要です。参照:スレッドプール.SetMaxThreads。
シングルスレッドアプリが重要な要件である場合(何らかの理由で)、もちろん、これらすべてを相互運用することができます。DLLインポート(参照例はこちら)
しかし、それは非常に複雑で危険な仕事:
なぜ APC を完了メカニズムとしてサポートしないのでしょうか? APC は、ユーザー コード用の汎用完了メカニズムとしては実際には適していません。APC によって導入される再入性を管理することはほぼ不可能です。たとえば、ロックをブロックすると、任意の I/O 完了がスレッドを乗っ取る可能性があります。独自のロックを取得しようとする可能性があり、ロック順序の問題が発生してデッドロックが発生する可能性があります。これを防ぐには、細心の注意を払った設計と、アラート可能な待機中に他のユーザーのコードが実行されないようにする機能、およびその逆の機能が求められます。これにより、APC の有用性が大幅に制限されます。
まとめると、シングルスレッドAPC と完了ポートを使用してすべての作業を実行する管理プロセスの場合は、手動でコーディングする必要があります。構築するのは危険で難しいでしょう。
単に大規模ネットワークに関しては、APC を使用しているため、ファミリを使い続けBeginXYZ
てもパフォーマンスが良好であることは間違いありません。スレッドと .NET の特定の実装の間でデータをマーシャリングするには、わずかなコストがかかります。
から:http://msdn.microsoft.com/en-us/magazine/cc300760.aspx
サーバーのスケールアップの次のステップは、非同期 I/O を使用することです。非同期 I/O を使用すると、スレッドの作成と管理の必要性が軽減されます。これにより、コードが大幅に簡素化され、より効率的な I/O モデルになります。非同期 I/O は、着信データと接続を処理するためにコールバックを使用するため、設定してスキャンするリストはなく、保留中の I/O を処理するために新しいワーカー スレッドを作成する必要もありません。
興味深い事実として、シングル スレッドは、完了ポートを使用して Windows 上で非同期ソケットを実行する最も高速な方法ではないということです。次を参照してください。http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml
サーバーの目標は、スレッドが不要なブロックを回避し、同時に複数のスレッドを使用して並列処理を最大化することで、コンテキスト スイッチをできるだけ少なくすることです。理想的なのは、すべてのプロセッサでクライアント要求をアクティブに処理するスレッドがあり、要求を完了したときに待機している追加の要求がある場合、それらのスレッドがブロックされないことです。ただし、これを正しく機能させるには、クライアント要求の処理中に I/O がブロックされたときに (処理の一部としてファイルから読み取る場合など)、アプリケーションが別のスレッドをアクティブ化する方法が必要です。