/// <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> /// 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; }