private static void GetResponses( IResponses responses, int numberResponsesToWait, List <Task <IResponse> > tasks, List <CancellationTokenSource> cancellations, bool notNull) { try { int countMessages = 0; while (countMessages < numberResponsesToWait) { int index = Task.WaitAny(tasks.ToArray()); if (index < 0) { return; } if (notNull) { if (tasks[index].Result != null) { lock (responses) { responses.Add(tasks[index].Result); countMessages++; } } } else { lock (responses) { responses.Add(tasks[index].Result); countMessages++; } } lock (cancellations) { // cancel task cancellations[index].Cancel(); cancellations.RemoveAt(index); } lock (tasks) { tasks.RemoveAt(index); } } // Cancel remaining sub-tasks MessageServiceClient.CancelSubTasks(cancellations); } catch (Exception e) { Log.Error(e.Message); } }
public IResponses RequestMulticast( IMessage message, Uri[] urls, int numberResponsesToWait, int timeout, bool notNull) { // block if frozen this.BlockFreezeState(message); if (urls.Length == 0) { return(new Responses()); } Log.Debug($"Multicast Request called with parameters: message: {message}, url: {urls}," + $"numberResponsesToWait: {numberResponsesToWait}, timeout: {timeout}"); if (numberResponsesToWait > urls.Length) { return(new Responses()); } else if (numberResponsesToWait < 0) { numberResponsesToWait = urls.Length; } List <Task <IResponse> > tasks = new List <Task <IResponse> >(); List <CancellationTokenSource> cancellations = new List <CancellationTokenSource>(); foreach (Uri url in urls) { CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); // Create Task and run async Task <IResponse> task = Task <IResponse> .Factory.StartNew(() => { using (cancellationTokenSource.Token.Register(() => Log.Debug("Task cancellation requested"))) { return(this.Request(message, url)); } }, cancellationTokenSource.Token); lock (tasks) { tasks.Add(task); } lock (cancellations) { cancellations.Add(cancellationTokenSource); } } // Wait until numberResponsesToWait IResponses responses = new Responses(); CancellationTokenSource cancellationTs = new CancellationTokenSource(); Task getResponses = Task.Factory.StartNew( () => { using (cancellationTs.Token.Register(() => { MessageServiceClient.CancelSubTasks(cancellations); })) { GetResponses(responses, numberResponsesToWait, tasks, cancellations, notNull); } }, cancellationTs.Token); try { bool taskCompleted = timeout < 0 ? getResponses.Wait(-1) : getResponses.Wait(timeout); if (taskCompleted) { Log.Debug($"Multicast response: {responses}"); return(responses); } cancellationTs.Cancel(); } catch (Exception e) { Log.Error(e.Message); } Log.Error("Multicast Request: Timeout, abort thread request."); return(responses); }