2016-03-04 43 views
1

我正在研究使用Bootstrap協議更新機器中多個節點的固件的重構代碼。當前的代碼看起來是這樣的(僞代碼):瞭解.NET中的等待和異步問題

public void StartUpdate() 
{ 
    Sokcet bootpSocket = new Socket(): 
    StateObject bootpState = new StateObject(bootpSocket); 

    BOOTPReceive(bootpState); 
    SendMagicPacket(); 

    while (!IsError && !IsUpdateComplete) 
    { 
     //wait for BOOTP/Update to finish before returning to caller 
    } 
} 

private void BOOTPReceive(object state) 
{ 
    bOOTPSocket.BeginReceive(PACKET_DATA, 0, PACKET_DATA.Length, 0, OnBOOTPReceive, state); 
} 

SendMagicPacket() 
{ 
    //create and send magic packet 
    // this will tell the node to respond with a BOOTPPacket 
} 

private void OnBOOTPReceive(IAsyncResult result) 
{ 
    StateObject state = (StateObject) result.AsyncState; 
    Socket handler = state.workSocket; 
    int bytesRcvd = handler.EndReceive(result); 
    packet = PACKET_DATA; 

    if(isValidBOOTP(packet)) 
    { 
     SendBOOTPResponse();  
    } 
    else{ 
     BOOTPReceive(); //keep listening for valid bootp response 
    } 
} 

private void SendBOOTPResponse() 
{ 
    UdpClient udpClient = new UdpClient(); 
    udpClient.BeginSend(packetData, packetData.Length, BROADCAST_IP, (int)UdpPort.BOOTP_CLIENT_PORT, OnBOOTPSend, udpClient); 
} 

private void OnBOOTPSend(IAsyncResult result) 
{ 
    UdpClient udpClient = (UdpClient)result.AsyncState; 
    int bytesSent = udpClient.EndSend(result); 
    udpClient.Close(); 
} 

我想要做的是轉換爲異步等待,但仍要求我不返回給調用者的時候了。我會如何去做這件事?這可能嗎?自從等待以來,這是否是正確的事情 - 異步傳播到頂端?

public void StartUpdate() 
{ 
    bool result = await SendMagicPacket(); 
    bool IsError = await BOOTPCommunication(); //Handles all of the BOOTP recieve/sends 
    //don't return to caller until BOOTPCommunication is completed. How do i do this? 
} 

回答

0

//等待BOOTP /更新完成之前返回給調用者

你根本不需要任何異步IO,因爲你wa nt等到所有操作完成。我假設你已經複製了一些示例代碼。大多數示例代碼使用異步套接字API。

將所有內容切換到同步套接字API並完成。

如果你想保持這種異步出於某種原因,你確實可以切換到等待並解開此代碼。你發佈的僞代碼看起來是一個很好的目標。不過,它強制周圍的方法是async Task

您可以通過使所有呼叫者以遞歸方式異步處理。如果您不需要保存線程,則可以阻止該任務並擁有大部分同步的調用鏈。但是,那時你會失去所有的異步優勢。

+0

你說得對,我一直在想這一切都是錯誤的。這全是同步的。我不知道爲什麼最後一個人異步做到這一點。 – stackErr

1

你需要等待兩個任務嘗試以下方法:什麼,我想這會看起來像

僞代碼

public async Task StartUpdate() 
    { 
     var resultTask = SendMagicPacket(); 
     var isErrorTask = BOOTPCommunication(); //Handles all of the BOOTP recieve/sends 

     await Task.WhenAll(new[]{resultTask, isErrorTask}); 
     //don't return to caller until BOOTPCommunication is completed. How do i do this? 
    } 
+1

這並不能解決我的問題。等待將立即返回到StartUpdates()調用者。 – stackErr

+0

@stackErr,'await'不會返回到'StartUpdate'方法的調用者。它只是指示CLR異步執行代碼並釋放線程。 –

-1

雷丁是在正確的軌道上,但我想你想要的是這樣的:

你需要等待兩個任務嘗試以下操作:

public async Task StartUpdate() 
{ 
    var resultTask = SendMagicPacket(); 
    var isErrorTask = BOOTPCommunication(); //Handles all of the BOOTP recieve/sends 

    Task.WhenAll(new[]{resultTask, isErrorTask}).Wait(); //Wait() will block so that the method doesn't return to the caller until both of the asynchronous tasks complete. 
} 

什麼,讓是SendMagicPacket和BOOTPCommunication兩者同時觸發,但等待兩者完成。使用該模式,您可以同時觸發N個事件,同時使用Wait()等待所有完成,以便方法本身同步返回。