internal async Task <IncomingMessage> PerformRequestAsync(CancellationToken cancellationToken) { int retryCounter = 0; IncomingMessage reply = null; var reassembler = new MessageReassembler(ctrl, this); Debug.WriteLine("timeout is " + waitRetryTimeout.TotalMilliseconds + "ms"); while (retryCounter++ <= retries) { // send message if (await outgoingMsg.SendAsync().ConfigureAwait(false)) { // if this request is for a reboot, we won't be able to receive the reply right away because the device is rebooting if ((outgoingMsg.Header.m_cmd == Commands.c_Monitor_Reboot) && retryCounter == 1) { // wait here for Task.Delay(2000).Wait(); } CancellationTokenSource source = new CancellationTokenSource(); // add a cancellation token to force cancel var timeoutCancelatioToken = source.Token.AddTimeout(waitRetryTimeout); // because we have an external cancellation token and the above timeout cancellation token, need to combine both var linkedCancelationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCancelatioToken).Token; try { // need to have a timeout to cancel the process task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both reply = await reassembler.ProcessAsync(linkedCancelationToken).ConfigureAwait(false); } catch { } finally { // ALWAYS cancel reassembler task source.Cancel(); } if (reply != null) { return(reply); } } else { // send failed Debug.WriteLine("SEND FAILED..."); } // something went wrong, retry with a progressive back-off strategy Task.Delay(200 * retryCounter).Wait(); } Debug.WriteLine("exceeded attempts count..."); return(null); }
internal async Task <IncomingMessage> PerformRequestAsync(CancellationToken cancellationToken) { int retryCounter = 0; IncomingMessage reply; var reassembler = new MessageReassembler(ctrl, this); while (retryCounter++ < retries) { // send message if (await outgoingMsg.SendAsync().ConfigureAwait(false)) { // need to have a timeout to cancel the process task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both reply = await reassembler.ProcessAsync(cancellationToken.AddTimeout(waitRetryTimeout)).ConfigureAwait(false); if (reply != null) { return(reply); } } else { // send failed Debug.WriteLine("SEND FAILED..."); } // something went wrong, retry with a progressive back-off strategy await Task.Delay(200 *retryCounter); } Debug.WriteLine("exceeded attempts count..."); return(null); }
internal async Task <IncomingMessage> PerformRequestAsync() { int retryCounter = 0; IncomingMessage reply = null; var reassembler = new MessageReassembler(ctrl, this); while (retryCounter++ <= retries) { //// TODO add cancel token argument here //// check for cancelation request //if (cancellationToken.IsCancellationRequested) //{ // // cancellation requested // Debug.WriteLine("cancelation requested"); // return null; //} Debug.WriteLine($"Performing {retryCounter}/{ (retries+1) } request attempt with {waitRetryTimeout.TotalMilliseconds}ms"); // create new cancelation token source CancellationTokenSource cTSource = new CancellationTokenSource(); // send message // add a cancellation token to force cancel, the send if (await outgoingMsg.SendAsync(cTSource.Token)) { // if this request is for a reboot, we won't be able to receive the reply right away because the device is rebooting if (outgoingMsg.Header.Cmd == Commands.c_Monitor_Reboot) { // done here, no reply will come return(reply); } Debug.WriteLine($"Processing reply now..."); // create new cancelation token for reply processor cTSource = new CancellationTokenSource(); try { // need to have a timeout to cancel the process task otherwise it may end up waiting forever for this to return // because we have an external cancellation token and the above timeout cancellation token, need to combine both reply = await reassembler.ProcessAsync(cTSource.Token.AddTimeout(waitRetryTimeout)); } catch (Exception ex) { Debug.WriteLine($"Exception occurred: {ex.Message}\r\n {ex.StackTrace}"); // ALWAYS cancel reassembler task on exception cTSource.Cancel(); } if (reply != null) { return(reply); } } else { // send failed Debug.WriteLine("SEND FAILED..."); } // something went wrong, retry with a progressive back-off strategy Task.Delay(200 * retryCounter).Wait(); } Debug.WriteLine($"Performing request exceeded attempts count..."); return(reply); }