/// <summary> /// see RepeatTemplate#WaitForResults /// </summary> /// <param name="state"></param> /// <returns></returns> protected override bool WaitForResults(IRepeatInternalState state) { IResultQueue <IResultHolder> queue = ((ResultQueueInternalState)state).ResultQueue; bool result = true; while (queue.IsExpecting()) { // Careful that no runnables that are not going to finish ever get // onto the queue, else this may block forever. IResultHolder future; try { future = queue.Take(); } catch (ThreadInterruptedException) { Thread.CurrentThread.Interrupt(); throw new RepeatException("InterruptedException while waiting for result."); } if (future.Error != null) { state.GetExceptions().Add(future.Error); result = false; } else { RepeatStatus status = future.Result; result = result && CanContinue(status); ExecuteAfterInterceptors(future.Context, status); } } Assert.State(queue.IsEmpty(), "Future results queue should be empty at end of batch."); return(result); }
/// <summary> /// see https://msdn.microsoft.com/fr-fr/library/ms244737.aspx /// </summary> /// <param name="disposing"></param> private void Dispose(bool disposing) { if (disposing && _results != null) { // free managed resources ((ResultHolderResultQueue)_results).Dispose(); _results = null; } }
/// <summary> /// Initialize the client with a DDPConnector, subscriber and ResultQueue. /// This shouldnt be user facing, but is necessary in the concrete classes. /// </summary> /// <returns>The init.</returns> /// <param name="connector">Connector for sending DDP Messages</param> /// <param name="subscriber">Subscriber for subscribing to DDP Messages</param> /// <param name="queue">Message queue</param> protected void Init(IDDPConnector connector, IDataSubscriber subscriber, IResultQueue queue) { this._connector = connector; this._subscriber = subscriber; this._queueHandler = queue; _subscriber.MessageReceived += (msg) => { if (MessageReceived != null) { MessageReceived(msg); } }; }
/// <summary> /// Use the TaskExecutor to generate a result. The /// internal state in this case is a queue of unfinished result holders of /// IResultHolder. The holder with the return value should not be /// on the queue when this method exits. The queue is scoped in the calling /// method so there is no need to synchronize access. /// </summary> /// <param name="context"></param> /// <param name="callback"></param> /// <param name="state"></param> /// <returns></returns> protected override RepeatStatus GetNextResult(IRepeatContext context, RepeatCallback callback, IRepeatInternalState state) { ExecutingRunnable runnable; IResultQueue <IResultHolder> queue = ((ResultQueueInternalState)state).ResultQueue; do { // Wrap the callback in a runnable that will add its result to the // queue when it is ready. runnable = new ExecutingRunnable(callback, context, queue); // Tell the runnable that it can expect a result. This could have // been in-lined with the constructor, but it might block, so it's // better to do it here, since we have the option (it's a private // class). runnable.Expect(); //Start the task possibly concurrently / in the future. _taskExecutor.Execute(new Task(delegate { runnable.Run(); })); // Allow termination policy to update its state. This must happen // immediately before or after the call to the task executor. Update(context); // Keep going until we get a result that is finished, or early // termination... }while (queue.IsEmpty() && !IsComplete(context)); IResultHolder result = queue.Take(); if (result.Error != null) { throw result.Error; } return(result.Result); }
/// <summary> /// /// </summary> /// <param name="throttleLimit"></param> public ResultQueueInternalState(int throttleLimit) { _results = new ResultHolderResultQueue(throttleLimit); }
public ExecutingRunnable(RepeatCallback callback, IRepeatContext context, IResultQueue<IResultHolder> queue) { _callback = callback; Context = context; _queue = queue; }
public ClientThread(IResultQueue requestQueue, string name, int seed) { Thread.CurrentThread.Name = name; _requestQueue = requestQueue; _random = new Random(seed); }
public ExecutingRunnable(RepeatCallback callback, IRepeatContext context, IResultQueue <IResultHolder> queue) { _callback = callback; Context = context; _queue = queue; }