/// <summary> /// Runs the function inside a message loop and continues pumping messages /// until the returned task completes. /// </summary> /// <returns>The completed task returned by the delegate's invocation</returns> public static Task Run(Func <Task> function) { using (SynchronizationContextSwitcher.Capture()) { Dispatcher dispatcher = Dispatcher.CurrentDispatcher; DispatcherFrame frame = new DispatcherFrame(exitWhenRequested: true); var message = new TaskFunctionLaunchMessage(function, dispatcher, frame); // queue up our first message before we run the loop dispatcher.BeginInvoke(new Action(message.LaunchMessageImpl)); // run the actual WPF message loop Dispatcher.PushFrame(frame); // PushFrame() has returned. Because we set Contine = false // in a continuation of the task, this can only occur if the task // has also completed. if (message.ReturnedTask != null) { message.ReturnedTask.RethrowForCompletedTasks(); } return(message.ReturnedTask); } }
/// <summary> /// Wraps a <see cref="Task{TResult}" /> into the Begin method of an APM pattern. /// </summary> /// <typeparam name="TResult">The type of the result.</typeparam> /// <param name="task">The task to wrap. May not be <c>null</c>.</param> /// <param name="callback">The callback method passed into the Begin method of the APM pattern.</param> /// <param name="state">The state passed into the Begin method of the APM pattern.</param> /// <returns> /// The asynchronous operation, to be returned by the Begin method of the APM pattern. /// </returns> public static IAsyncResult ToBegin <TResult>(Task <TResult> task, AsyncCallback callback, object state) { TaskCompletionSource <TResult> tcs = new TaskCompletionSource <TResult>(state, TaskCreationOptions.RunContinuationsAsynchronously); SynchronizationContextSwitcher.NoContext(() => CompleteAsync(task, callback, tcs)); return(tcs.Task); }
public static Task Run(Func <Task> asyncMethod) { using (SynchronizationContextSwitcher.Capture()) { var customContext = new Context(); SynchronizationContext.SetSynchronizationContext(customContext); var task = asyncMethod.Invoke(); if (task != null) { // register a continuation with the task, which will shut down the loop when the task completes. task.ContinueWith(_ => customContext.WorkQueue.Shutdown(), TaskContinuationOptions.ExecuteSynchronously); } else { // the delegate returned a null Task (VB/C# compilers never do this for async methods) // we don't have anything to register continuations with in this case, so just return immediately return(task); } customContext.WorkQueue.ExecuteWorkQueueLoop(); task.RethrowForCompletedTasks(); return(task); } }
/// <summary> /// Runs the action inside a message loop and continues looping work items /// as long as any asynchronous operations have been registered /// </summary> public static void Run(Action asyncAction) { using (SynchronizationContextSwitcher.Capture()) { var customContext = new VoidContext(); SynchronizationContext.SetSynchronizationContext(customContext); // Do an explicit increment/decrement. // Our sync context does a check on decrement, to see if there are any // outstanding asynchronous operations (async void methods register this correctly). // If there aren't any registerd operations, then it will exit the loop customContext.OperationStarted(); try { asyncAction.Invoke(); } finally { customContext.OperationCompleted(); } customContext.WorkQueue.ExecuteWorkQueueLoop(); // ExecuteWorkQueueLoop() has returned. This must indicate that // the operation count has fallen back to zero. } }
/// <summary> /// Wraps a <see cref="Task"/> into the Begin method of an APM pattern. /// </summary> /// <param name="task">The task to wrap.</param> /// <param name="callback">The callback method passed into the Begin method of the APM pattern.</param> /// <param name="state">The state passed into the Begin method of the APM pattern.</param> /// <returns>The asynchronous operation, to be returned by the Begin method of the APM pattern.</returns> public static IAsyncResult ToBegin(Task task, AsyncCallback callback, object state) { var tcs = new TaskCompletionSource <object>(state, TaskCreationOptions.RunContinuationsAsynchronously); using (SynchronizationContextSwitcher.NoContext()) CompleteAsync(task, callback, tcs); return(tcs.Task); }
public override Task <int> ReadAsync([NotNull] byte[] buffer, int offset, int count, CancellationToken token) { CheckDisposed(); return(SynchronizationContextSwitcher.NoContext(async() => { count = Math.Min(count, _row.ColumnLen - _row.PosInColumn); var read = await _row.Buffer.ReadAllBytes(buffer, offset, count, true, true); _row.PosInColumn += read; return read; })); }
/// <summary> /// Runs the action inside a message loop and continues pumping messages /// as long as any asynchronous operations have been registered /// </summary> public static void Run(Action asyncAction) { using (SynchronizationContextSwitcher.Capture()) { Dispatcher dispatcher = Dispatcher.CurrentDispatcher; DispatcherFrame frame = new DispatcherFrame(exitWhenRequested: true); var message = new AsyncActionLaunchMessage(asyncAction, dispatcher, frame); // queue up our first message before we run the loop dispatcher.BeginInvoke(new Action(message.LaunchMessageImpl)); // run the actual WPF message loop Dispatcher.PushFrame(frame); // PushFrame() has returned. This must indicate that // the operation count has fallen back to zero. } }