private void AttachCompletionToWaitItem <K>(Session session, DuplexWaitItem <K> waitItem, TimeSpan timeout) { var cancelTokenSource = new CancellationTokenSource(); Action clear = () => { lock (_Sync) { _WaitDic.Remove(waitItem.MessageId); } cancelTokenSource.Cancel(); waitItem.CancelTask = null; }; waitItem.CancelTask = Task .Delay(timeout, cancelTokenSource.Token) .ContinueWith(t => { if (t.IsCanceled) { return; } waitItem.CompletionSource?.TrySetException(new TimeoutException()); clear(); }); waitItem.CompletionSource.Task.ContinueWith(t => { clear(); }); }
public Task <K> Send <T, K>(Session session, T message, TimeSpan?timeout = null, bool wait = true) { if (timeout == null) { timeout = TimeSpan.FromSeconds(30); } var request = new DuplexRequest() { MessageId = Guid.NewGuid(), Message = SerializeManager.Current.Serialize(message) }; var bytes = SerializeManager.Current.Serialize(request); if (wait) { var waitItem = new DuplexWaitItem <K>(request.MessageId); lock (_Sync) { _WaitDic.Add(waitItem.MessageId, waitItem); } AttachCompletionToWaitItem(session, waitItem, timeout.Value); _CommunicationBase.SendDataInternal(session, bytes); return(waitItem.CompletionSource.Task); } else { _CommunicationBase.SendDataInternal(session, bytes); return(null); } }