public void CancelSender(TheThing myBaseThingForLogging, CancellationToken?masterToken = null, bool triggerCancelOnly = false) { StopThingMatcher(); SenderTaskInfo previousTaskInfo = null; if (pendingHistoryLoops.TryGetValue(cdeMID, out previousTaskInfo)) { try { if (!masterToken.HasValue) { masterToken = TheBaseAssets.MasterSwitchCancelationToken; } try { previousTaskInfo.cancelSource.Cancel(); } catch { } if (triggerCancelOnly) { return; } int count = 0; const int timePerLoop = 1000; const int timeout = 1 * 60; while (!masterToken.Value.IsCancellationRequested && previousTaskInfo.task.Status != TaskStatus.Canceled && previousTaskInfo.task.Status != TaskStatus.Faulted && previousTaskInfo.task.Status != TaskStatus.RanToCompletion && count < timeout ) { try { previousTaskInfo.task.Wait(timePerLoop, masterToken.Value); } catch (OperationCanceledException) { } count++; if (count >= timeout) { TheBaseAssets.MySYSLOG.WriteToLog(95275, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(myBaseThingForLogging.EngineName, "Connect", eMsgLevel.l2_Warning, $"Waiting on cancel previous send loop for {myBaseThingForLogging.FriendlyName} - {cdeMID}: timeout after {count * timePerLoop} ms. Retrying.")); count = 0; } } if (count >= timeout) { TheBaseAssets.MySYSLOG.WriteToLog(95275, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(myBaseThingForLogging.EngineName, "Connect", eMsgLevel.l2_Warning, $"Unable to cancel previous send loop for {myBaseThingForLogging.FriendlyName} - {cdeMID}: timeout after {count * timePerLoop} ms")); } previousTaskInfo.cancelSource?.Dispose(); pendingHistoryLoops.RemoveNoCare(cdeMID); } catch (Exception e) { TheBaseAssets.MySYSLOG.WriteToLog(95257, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM(myBaseThingForLogging.EngineName, "Connect", eMsgLevel.l6_Debug, String.Format("Exception while cancelling previous send loop for thing {0}: {1}", cdeMID, TheCommonUtils.GetAggregateExceptionMessage(e)))); } } }
public bool StartSender(TheThing myBaseThing, TheSenderThing senderClone, Func <object, Task> senderLoop, CancellationToken masterToken) { if (pendingHistoryLoops.TryGetValue(cdeMID, out var previousTaskInfo)) { if (previousTaskInfo.senderThing.HistoryToken == this.HistoryToken && previousTaskInfo.senderThing.IsEqual(this) && previousTaskInfo.senderThing.IsHistoryTokenCurrent() && !previousTaskInfo.task.IsCompleted && !previousTaskInfo.cancelSource.IsCancellationRequested) { return(true); } } CancelSender(myBaseThing, masterToken); var cancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(masterToken, TheBaseAssets.MasterSwitchCancelationToken); var senderTaskInfo = new SenderTaskInfo { owner = myBaseThing, senderThing = senderClone, cancelSource = cancelTokenSource }; var task = TheCommonUtils.cdeRunTaskChainAsync("HistorySenderLoop", senderLoop, senderTaskInfo, true); //var task = senderLoop(senderTaskInfo); senderTaskInfo.task = task; pendingHistoryLoops[this.cdeMID] = senderTaskInfo; return(true); }