var options = new ParallelOptions
{
    MaxDegreeOfParallelism = 8,
    CancellationToken = cancellationToken
};
await Parallel.ForEachAsync(endpoints, options,
    async (endpoint, token) =>
    {
        var result = await ProbeAsync(endpoint, target, token);
        observations.Add(result);
    });

エンドポイントごとにタスクを起動するのではなく、上限付きのワーカープールを使います。許可された公開対象への検査では、無料プロキシリストが候補行を提供します。プローブを組み立てるときは各項目のプロトコルを保ってください。この .NET のスケジューリング断片は、プロキシを認識する ProbeAsync とスレッドセーフな observations コレクターを前提としています。8 という値は例示的な上限であり、測定された最適値ではありません。プローブには試行ごとの上限とジョブ全体のキャンセルが依然として必要です。

完了順が異なっても、完了した結果は必ずその入力と組にして保持します。プロトコル、エンドポイント、対象、メソッド、経過時間、結果を記録します。接続失敗、プロキシのログイン拒否、CONNECT の拒否、サイトから応答が返ったことは、それぞれ別の観測です。

TCP ポートが開いたことはプロキシ交渉の証明になりません。プロキシアドレスをウェブサイトとして取得することも、対象への要求に使うこととは別です。

必要な能力に合わせて対象とメソッドを選びます。HEAD は本文の通信を節約できますが、GET が有用な内容を返すことは証明しません。サイトが一方を拒否し他方を許可することもあります。HTTPS は平文 HTTP にはない CONNECT と宛先 TLS を追加します。出口アドレスは、設定された入口とは別の、宛先側の観測です。

作業を制限すると、検査器が経路を評価する前に自身のソケット、メモリ、スケジューラを使い果たすのを防げます。段階的な結果は、1 つの成功した宛先だけでエンドポイントが普遍的に良好になるわけではないと保ちつつ、選択方針に役立ちます。

関連記事