/// <summary> /// EAP (Event-based Asynchronous Pattern : 이벤트기반 비동기 패턴) 작업에서, 작업 완료시의 후속조치를 정의합니다. /// </summary> /// <typeparam name="T">비동기 작업 결과물의 수형</typeparam> /// <param name="tcs">비동기 작업을 표현하는 delegate</param> /// <param name="e">비동기 작업완료 이벤트 인자</param> /// <param name="getResult">작업완료 시에 결과 반환 메소드</param> /// <param name="unregisterHandler">작업완료 이벤트 핸들러를 등록취소하는 Action</param> public static void HandleCompletion <T>(TaskCompletionSource <T> tcs, AsyncCompletedEventArgs e, Func <T> getResult, Action unregisterHandler) { tcs.ShouldNotBeNull("tcs"); e.ShouldNotBeNull("e"); if (e.UserState != tcs) { return; } getResult.ShouldNotBeNull("getResult"); if (e.Cancelled) { tcs.TrySetCanceled(); } else if (e.Error != null) { tcs.TrySetException(e.Error); } else { tcs.TrySetResult(getResult()); } if (unregisterHandler != null) { unregisterHandler(); } }
/// <summary> /// <paramref name="task"/>의 상태에 따라 <paramref name="resultSetter"/>의 작업 결과를 설정을 시도합니다. /// </summary> /// <typeparam name="TResult">작업 결과의 수형</typeparam> /// <param name="resultSetter">작업 결과를 설정할 인스턴스</param> /// <param name="task">작업</param> /// <returns>설정 성공 여부</returns> public static bool TrySetFromTask <TResult>(this TaskCompletionSource <TResult> resultSetter, Task task) { resultSetter.ShouldNotBeNull("resultSetter"); task.ShouldNotBeNull("task"); if (IsDebugEnabled) { log.Debug("resultSetter의 작업 결과를 task의 상태에 따라 설정을 시도합니다... task.Status=[{0}]", task.Status); } switch (task.Status) { case TaskStatus.RanToCompletion: return(resultSetter.TrySetResult(task is Task <TResult>?((Task <TResult>)task).Result: default(TResult))); case TaskStatus.Faulted: return(resultSetter.TrySetException(task.Exception.InnerExceptions)); case TaskStatus.Canceled: return(resultSetter.TrySetCanceled()); default: throw new InvalidOperationException("작업이 완료되지 않았습니다!!!"); } }
internal static IEnumerable <Task> TrackedSequenceInternal(IEnumerable <Func <Task> > functions, TaskCompletionSource <IList <Task> > tcs) { tcs.ShouldNotBeNull("tcs"); if (IsDebugEnabled) { log.Debug("함수 시퀀스를 반복적으로 호출하여, 결과로 반환되는 Task를 열거합니다."); } var tasks = new List <Task>(); foreach (var func in functions) { Task nextTask = null; try { nextTask = func(); } catch (Exception ex) { if (log.IsWarnEnabled) { log.WarnException("함수 호출에서 예외가 발생했습니다.", ex); } tcs.TrySetException(ex); } if (nextTask == null) { yield break; } yield return(nextTask); if (nextTask.IsFaulted) { break; } } tcs.TrySetResult(tasks); }