/// <summary> /// Executes the task. /// </summary> /// <param name="scheduler">The scheduler.</param> /// <param name="yieldToken">Token to observe for yield requests.</param> /// <returns><c>true</c> if the task has been completed; otherwise, <c>false</c>.</returns> public bool Execute(IScheduler scheduler, YieldToken yieldToken) { Debug.Assert(scheduler != null, "Scheduler should not be null."); _processor.Process(BatchSize, yieldToken); return(false); }
public void YieldToken_Basics() { var s = new MyYieldTokenSource(); var t = new YieldToken(s); foreach (var token in new[] { t, s.Token, }) { s.IsYieldRequested = false; Assert.IsFalse(token.IsYieldRequested); s.IsYieldRequested = true; Assert.IsTrue(token.IsYieldRequested); } var t1 = t; var t2 = t; Assert.IsTrue(t1.Equals((object)t2)); Assert.IsFalse(t1.Equals("bar")); Assert.IsTrue(t1.Equals(t2)); Assert.IsTrue(t1 == t2); Assert.IsFalse(t1 != t2); Assert.IsFalse(t == YieldToken.None); Assert.IsFalse(YieldToken.None == t); Assert.IsFalse(YieldToken.None.Equals(t)); Assert.IsFalse(YieldToken.None.Equals((object)t)); Assert.IsFalse(t.Equals(YieldToken.None)); Assert.IsFalse(t.Equals((object)YieldToken.None)); Assert.AreNotEqual(0, t.GetHashCode()); }
public void Process(int batchSize, YieldToken token) { if (token.IsYieldRequested) { return; } bool completed = default; Exception error = default; int eventCount; _itemProcessed = true; if (_eventBuffer.Length < batchSize) { _eventBuffer = new TResult[batchSize]; } lock (_queue) { eventCount = Math.Min(_queue.Count, batchSize); _queue.CopyTo(0, _eventBuffer, 0, eventCount); _queue.RemoveRange(0, eventCount); if (_queue.Count == 0) { completed = _completed; error = _error; } } int i; for (i = 0; i < eventCount && !token.IsYieldRequested; ++i) { var evt = _eventBuffer[i]; var success = false; try { _observer.OnNext(evt); success = true; OnDequeued(evt); } catch (Exception ex) { // // Failure to deliver one message is final. We can't retry without triggering duplication of // side-effects on the downstream observers, nor can we skip messages because it'd break the // sequential nature of observable sequences. As such, we can do nothing but terminate. // TraceObserverError("OnNext", ex, evt); throw; } finally { if (!success) { Dispose(); } } } if (i != eventCount) { lock (_queue) { _queue.InsertRange(0, _eventBuffer.Take(eventCount).Skip(i)); } return; } if (token.IsYieldRequested) { return; } if (error != null) { try { _observer.OnError(error); } catch (Exception ex) { TraceObserverError("OnError", ex, error); throw; } finally { Dispose(); } } if (completed) { try { _observer.OnCompleted(); } catch (Exception ex) { TraceObserverError("OnCompleted", ex); throw; } finally { Dispose(); } } }
/// <summary> /// Executes the task. /// </summary> /// <param name="scheduler">The scheduler.</param> /// <param name="yieldToken">Token to observe for yield requests.</param> /// <returns><c>true</c> if the task has been completed; otherwise, <c>false</c>.</returns> public bool Execute(IScheduler scheduler, YieldToken yieldToken) { Debug.Assert(scheduler != null, "Scheduler should not be null."); return(_action(_state, yieldToken)); }