2016-05-26 5 views
0

以下のコードでWaitAllに問題があります。このメソッドはIPアドレスとポート(WMIポート135をスキャンしています)のリストを受け取り、ポートが開いているIPアドレスのリストを返します。私はこのコードを遅くすると、実行して正しいシステムを返すようにWaitAllが正しく実装されていないと信じています。ありがとう。開いているTCPポートをスキャンするためのスレッド処理

private static List<IPAddress> openSystems = new List<IPAddress>(); 

public static List<IPAddress> Scan(List<IPAddress> addresses, ushort port) 
{ 
    int count = addresses.Count; 
    Task[] tasks = new Task[count]; 

    //Loop through ip address 
    for(int x = 0; x <= count -1; x++) 
    { 
     tasks[x] = Task.Factory.StartNew(() => 
     { 
      using (TcpClient tcp = new TcpClient()) 
      { 
       try 
       { 
        Console.WriteLine("Trying to get into {0}", addresses[x]); 
        tcp.Connect(addresses[x], port); 
        openSystems.Add(addresses[x]); 
       } 
       catch 
       { 
        Console.WriteLine("Can't get into {0}", addresses[x]); 
        //ignore exceptions 
       } 
      } 
     }); 
    } 

    Task.WaitAll(tasks); 
    return openSystems; 
} 
+2

問題は何ですか?そして、どのように「コードを遅くする」のですか?また、 'openSystems.Add(addresses [x])'の周りに 'lock'が必要です。[' concurrent collections'](https://msdn.microsoft.com/en-us/library/system) .collections.concurrent(v = vs.110).aspx) – Quantic

+0

例外を無視しないでください_常に_悪い考えですか? –

答えて

1

コードでは無視されるいくつかのベストプラクティスがあります。

あなたがれるtcpClientのConnectAsyncメソッドを呼び出す必要がありますし、あなたがTask.WaitAllしかしawait Task.WhenAll

メソッドのシグネチャは、その後public static Task> ScanAsync(List addresses, ushort port)になり、あなたはどこにコーディングすることを待つことができますを使用してはならないTask.Factory.StartNew

への呼び出しを取り除きますが呼び出されます。

あなたは別のスレッドに対してopenSystemsのリストにアクセスしています。リストはスレッドセーフではありませんので、並行コレクションを使用するか、そうでなければ実行してください。

public static async Task<List<IPAddress>> ScanAsync(List<IPAddress> addresses, ushort port) 
{ 
    var tasks = addresses.Select(a => CheckIpAsync(a, port); 

    await Task.WhenAll(tasks); 
    return openSystems; 
} 

private async Task CheckIpAsync(IPAddress address, ushort port) 
{ 
    using (TcpClient tcp = new TcpClient()) 
    { 
     try 
     { 
      Console.WriteLine("Trying to get into {0}", address); 
      await tcp.ConnectAsync(address, port); 
      openSystems.Add(address); 
     } 
     catch 
     { 
      Console.WriteLine("Can't get into {0}", address); 
      //ignore exceptions 
     } 
    } 
} 

これは私が見つけることができないので、まだあなたの質問に答えないかもしれません。しかし、より良い実装を示しています。

+0

ご協力いただきありがとうございます。私はベストプラクティスに精通していません。私はScanAsyncがなぜタスクタイプであるのかよく分かりません。私はopenSystemsを返すことはできません。私はあなたのコードに "待っているTask.WhenAll(タスク)"行に問題があり、またopenSystemsを返す。私はコンカレントコレクションを使用していなかったことを指摘してくれてありがとう。あなたはこのデータのために並行辞書をお勧めしますか? –

+0

@JoshuaEllis申し訳ありませんが、私は重要な部分を忘れました。私は答えを更新しました。私はあなたが持っていた問題は、私の答えのコードがコンパイルされていないということです。 –

+0

CheckIpAsyncにawaitステートメントがあるので、タスクを返します。 答えのコードを使用すると、別のスレッドでリストを更新していないため、コンカレントコレクションは必要ありません。 async/awaitの説明については、https://msdn.microsoft.com/en-us/library/mt674882.aspxを参照してください。どのようなタスク関連のコードを使用する前に、基本の背後にあることを把握することが基本的です。 –

関連する問題