2013-03-17 5 views
2

주어진 ips에서 익명 연결을 허용하는 모든 ftp 서버를 찾으려고합니다.비동기 FTP 통화가 끝나지 않음

기본적으로 확인하고 싶은 IP를 얻은 다음 각각에 ListDirectory를 시도합니다. 예외가 없으면 ftp가 존재하며 액세스 할 수 있습니다.

저는 비동기 방법을 사용하여 IP를 확인하므로 작업 속도가 훨씬 빠릅니다. 그러나 모든 비동기 호출이 반환 될 때까지 기다려야합니다. 이렇게하려면, 내가이 비동기 호출의 수에 카운터를 유지 문제는이 카운터에 도착하지 0입니다

다음과 같이 내 코드는 같습니다

가 IP를 반복하는 :

static int waitingOn; 
public static IEnumerable<Uri> GetFtps() 
{ 
    var result = new LinkedList<Uri>(); 
    waitingOn = 0; 

    IPNetwork ipn = IPNetwork.Parse("192.168.72.0/21"); 
    IPAddressCollection ips = IPNetwork.ListIPAddress(ipn); 

    foreach(var ip in ips) 
    { 
     VerifyFtpAsync(ip, result); 
    } 

    while (waitingOn > 0) 
    { 
     Console.WriteLine(waitingOn); 
     System.Threading.Thread.Sleep(1000); 
    } 

    return result; 
} 

각각의 IP 확인하기 : 당신이 이벤트를 작성하지 않는 한

public async static void VerifyFtpAsync(IPAddress ip, LinkedList<Uri> ftps) 
{ 
    ++waitingOn; 
    try 
    { 
     Uri serverUri = new Uri("ftp://" + ip); 
     FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri); 
     request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; 
     request.Timeout = 10000; 
     request.Credentials = new NetworkCredential("anonymous", "[email protected]"); 

     FtpWebResponse response = (FtpWebResponse) await request.GetResponseAsync(); 

     // If we got this far, YAY! 
     ftps.AddLast(serverUri); 
    } 
    catch (WebException) 
    { 
    } 
    --waitingOn; 
} 
+1

코드가 hsip으로 설정된 부분이 누락 된 것 같습니다. 또한 VerifyFtpAsync에 대한 호출에서 누락되었습니다. 아마도 VerifyFtpAsync 래퍼 함수가있을 것입니다. –

+0

그 변경을 잊어 버렸습니다. Uri의 HashSet (hsip)에 어떤 호출이 반환되지 않았는지 알기 위해 추가하려고했지만, 결국 HashSet에는 waitingOn == 4 대신 네 개의 null 요소가 있습니다. – roim

+0

나는 당신이 기다리고있는 라인을 주석 처리하고 그것이 완료되었는지를보고 시작할 것입니다. 미안하지만, 이건별로 도움이 안돼. –

답변

1

먼저 async void를 사용해서는 안됩니다을 매니저.

async 메소드가 병렬로 실행될 수있는 경우 (예 :이 코드가 콘솔 앱에서 실행되는 경우) 변수 및 컬렉션을 멀티 스레드 액세스로부터 보호해야합니다. 귀하의 경우에는 수동 카운터 대신 Task.WhenAll을 사용하고 공유 컬렉션을 제거하는 것이 좋습니다.

public async static Task<Uri> VerifyFtpAsync(IPAddress ip) 
{ 
    try 
    { 
    ... 
    return serverUri; 
    } 
    catch (WebException) 
    { 
    return null; 
    } 
} 

... 

var ipTasks = ips.Select(ip => VerifyFtpAsync(ip)); 
var allResults = await Task.WhenAll(ipTasks); 
var result = allResults.Where(url => url != null).ToArray(); 
+0

난 아직도 내 문제를 해결, 모든 비동기 호출을 하나의 스레드에서 실행 해야하는 건 아니야? (기다리고있는 것이 다른 스레드에서 돌아갈 수는 있지만 내 변수에는 액세스하지 못했습니다.) 아, Linq awesomeness +1에 대한 대답 – roim

+1

@rOim 그게 당신이 그것을 부름에 따라 다릅니다. 그것은 콘솔 응용 프로그램 또는'ThreadPool' 스레드에서 온 경우, 연속성은 단일 스레드에서 실행되지 않습니다 (운이 좋으면 제외). – svick

+0

이 솔루션은 가끔 중단됩니다. var ipTasks = ips.Select (ip => VerifyFtpAsync (ip) .ContinueWith (t => {Console.WriteLine (Interlocked.Increment) + "/"+ 합계); 리턴 할 ipTasks 행을 수정했습니다. t.Result;}))); 그리고 때때로 2047/2048에 출력이 중지됩니다. – roim

관련 문제