static async Task CreateDialog(ContentDialog Dialog, bool awaitPreviousDialog) { if (ActiveDialog != null) { if (awaitPreviousDialog) { ActiveDialog.Hide(); } else { switch (Info.Status) { case AsyncStatus.Started: Info.Cancel(); break; case AsyncStatus.Completed: Info.Close(); break; case AsyncStatus.Error: break; case AsyncStatus.Canceled: break; } } } ActiveDialog = Dialog; ActiveDialog.Closing += ActiveDialog_Closing; Info = ActiveDialog.ShowAsync(); }
protected void CancelPreviousAndShowDialog(ContentDialog dialog) { if (previous == null) previous = dialog; CancelPreviousDialog(); LastDialogControl = dialog.ShowAsync(); }
public AsyncInfoToObservableBridge(IAsyncInfo info, Action <IAsyncInfo, Action <IAsyncInfo, AsyncStatus> > onCompleted, Func <IAsyncInfo, TResult> getResult, Action <IAsyncInfo, Action <IAsyncInfo, TProgress> > onProgress, IProgress <TProgress> progress, bool multiValue) { _onCompleted = onCompleted; _getResult = getResult; _subject = new AsyncSubject <TResult>(); if (onProgress != null) { onProgress(info, (iai, p) => { if (multiValue && getResult != null) { _subject.OnNext(getResult(iai)); } if (progress != null) { progress.Report(p); } }); } Done(info, info.Status, true); }
protected void CancelPreviousDialog() { if (LastDialogControl != null) { LastDialogControl.Cancel(); LastDialogControl = null; } }
public IDisposable AddPendingDialog(IAsyncInfo asyncInfo) { var weakReference = new WeakReference <IAsyncInfo>(asyncInfo); _pendingDialogs.Add(weakReference); return(new PendingDialogAwaiter(this, weakReference)); }
internal void StreamOperationCompletedCallback(IAsyncInfo completedOperation, AsyncStatus unusedCompletionStatus) { try { if (_callbackInvoked) { throw new InvalidOperationException(SR.InvalidOperation_MultipleIOCompletionCallbackInvocation); } _callbackInvoked = true; // This happens in rare stress cases in Console mode and the WinRT folks said they are unlikely to fix this in Dev11. // Moreover, this can happen if the underlying WinRT stream has a faulty user implementation. // If we did not do this check, we would either get the same exception without the explaining message when dereferencing // completedOperation later, or we will get an InvalidOperation when processing the Op. With the check, they will be // aggregated and the user will know what went wrong. if (completedOperation == null) { throw new NullReferenceException(SR.NullReference_IOCompletionCallbackCannotProcessNullAsyncInfo); } _completedOperation = completedOperation; // processCompletedOperationInCallback == false indicates that the stream is doing a blocking wait on the waitHandle of this IAsyncResult. // In that case calls on completedOperation may deadlock if completedOperation is not free threaded. // By setting processCompletedOperationInCallback to false the stream that created this IAsyncResult indicated that it // will call ProcessCompletedOperation after the waitHandle is signalled to fetch the results. if (_processCompletedOperationInCallback) { ProcessCompletedOperation(); } } catch (Exception ex) { _bytesCompleted = 0; _errorInfo = ExceptionDispatchInfo.Capture(ex); } finally { _completed = true; Interlocked.MemoryBarrier(); // From this point on, AsyncWaitHandle would create a handle that is readily set, // so we do not need to check if it is being produced asynchronously. if (_waitHandle != null) { _waitHandle.Set(); } } if (_userCompletionCallback != null) { _userCompletionCallback(this); } }
internal void CloseStreamOperation() { try { if (_asyncStreamOperation != null) { _asyncStreamOperation.Close(); } } catch { } _asyncStreamOperation = null; }
internal bool CancelStreamOperation() { if (_callbackInvoked) { return(false); } if (_asyncStreamOperation != null) { _asyncStreamOperation.Cancel(); _asyncStreamOperation = null; } return(true); }
/// <summary>Registers the async operation for cancellation.</summary> /// <param name="asyncInfo">The asynchronous operation.</param> /// <param name="cancellationToken">The token used to request cancellation of the asynchronous operation.</param> internal void RegisterForCancellation(IAsyncInfo asyncInfo) { Debug.Assert(asyncInfo != null); try { if (_ct.CanBeCanceled && !_completing) { // benign race on m_completing... it's ok if it's not up-to-date. var ctr = _ct.Register(ai => ((IAsyncInfo)ai).Cancel(), asyncInfo); // delegate cached by compiler // The operation may already be completing by this time, in which case // we might need to dispose of our new cancellation registration here. bool disposeOfCtr = false; lock (StateLock) { if (_completing) { disposeOfCtr = true; } else { _ctr = ctr; // under lock to avoid torn writes } } if (disposeOfCtr) { ctr.TryDeregister(); } } } catch (Exception ex) { // We do not want exceptions propagating out of the AsTask / GetAwaiter calls, as the // Completed handler will instead store the exception into the returned Task. // Such exceptions should cause the Completed handler to be invoked synchronously and thus the Task should already be completed. if (!base.Task.IsFaulted) { Debug.Assert(false, String.Format("Expected base task to already be faulted but found it in state {0}", base.Task.Status)); base.TrySetException(ex); } } }
protected internal StreamOperationAsyncResult(IAsyncInfo asyncStreamOperation, AsyncCallback userCompletionCallback, Object userAsyncStateInfo, bool processCompletedOperationInCallback) { if (asyncStreamOperation == null) throw new ArgumentNullException("asyncReadOperation"); _userCompletionCallback = userCompletionCallback; _userAsyncStateInfo = userAsyncStateInfo; _asyncStreamOperation = asyncStreamOperation; _completed = false; _callbackInvoked = false; _bytesCompleted = 0; _errorInfo = null; _processCompletedOperationInCallback = processCompletedOperationInCallback; }
/// <summary> /// Run the task with the given timeout, and interval. /// Once the task completes/cancels/errors or the timer pops /// the function will return. /// </summary> /// <param name="task">The task to wait for</param> /// <returns>True on completion, false on cancel/error/timeout</returns> public bool timeTask(IAsyncInfo task) { DateTime stopAt = DateTime.Now.AddMilliseconds(timeoutMillisecs); while (stopAt > DateTime.Now) { // check if the task has finished if (task.Status == AsyncStatus.Canceled || task.Status == AsyncStatus.Completed || task.Status == AsyncStatus.Error) { break; } // wait and try again timer.WaitOne(Math.Min( interval, (stopAt - DateTime.Now).Milliseconds)); } return(task.Status == AsyncStatus.Completed); }
protected internal StreamOperationAsyncResult(IAsyncInfo asyncStreamOperation, AsyncCallback userCompletionCallback, object userAsyncStateInfo, bool processCompletedOperationInCallback) { if (asyncStreamOperation == null) { throw new ArgumentNullException("asyncReadOperation"); } _userCompletionCallback = userCompletionCallback; _userAsyncStateInfo = userAsyncStateInfo; _asyncStreamOperation = asyncStreamOperation; _completed = false; _callbackInvoked = false; _bytesCompleted = 0; _errorInfo = null; _processCompletedOperationInCallback = processCompletedOperationInCallback; }
internal void RegisterForCancellation(IAsyncInfo asyncInfo) { Debug.Assert(asyncInfo != null); try { if (_ct.CanBeCanceled && !_completing) { var ctr = _ct.Register(ai => ((IAsyncInfo)ai).Cancel(), asyncInfo); bool disposeOfCtr = false; lock (this) { if (_completing) { disposeOfCtr = true; } else { _ctr = ctr; } } if (disposeOfCtr) { ctr.Dispose(); } } } catch (Exception ex) { if (!base.Task.IsFaulted) { Debug.Fail($"Expected base task to already be faulted but found it in state {base.Task.Status}"); base.TrySetException(ex); } } }
private static void rethrow(IAsyncInfo asyncInfo) { System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(asyncInfo.ErrorCode).Throw(); throw new Exception("Error of wrapped asyncinfo.", asyncInfo.ErrorCode); }
public static void NoWarning(this IAsyncInfo asyncInfo) { /* Do nothing */ }
internal override void ProcessConcreteCompletedOperation(IAsyncInfo completedOperation, out Int64 bytesCompleted) { ProcessConcreteCompletedOperation((IAsyncOperation<Boolean>)completedOperation, out bytesCompleted); }
/// <summary>Completes the task from the completed asynchronous operation.</summary> /// <param name="asyncInfo">The asynchronous operation.</param> /// <param name="getResultsFunction">A function used to retrieve the TResult from the async operation; may be null.</param> /// <param name="asyncStatus">The status of the asynchronous operation.</param> private void Complete(IAsyncInfo asyncInfo, Func <IAsyncInfo, TResult> getResultsFunction, AsyncStatus asyncStatus) { if (asyncInfo == null) { throw new ArgumentNullException(nameof(asyncInfo)); } Contract.EndContractBlock(); AsyncCausalitySupport.RemoveFromActiveTasks(this.Task); try { Debug.Assert(asyncInfo.Status == asyncStatus, "asyncInfo.Status does not match asyncStatus; are we dealing with a faulty IAsyncInfo implementation?"); // Assuming a correct underlying implementation, the task should not have been // completed yet. If it is completed, we shouldn't try to do any further work // with the operation or the task, as something is horked. bool taskAlreadyCompleted = Task.IsCompleted; Debug.Assert(!taskAlreadyCompleted, "Expected the task to not yet be completed."); if (taskAlreadyCompleted) { throw new InvalidOperationException(SR.InvalidOperation_InvalidAsyncCompletion); } // Clean up our registration with the cancellation token, noting that we're now in the process of cleaning up. CancellationTokenRegistration ctr; lock (StateLock) { _completing = true; ctr = _ctr; // under lock to avoid torn reads _ctr = default(CancellationTokenRegistration); } ctr.TryDeregister(); // It's ok if we end up unregistering a not-initialized registration; it'll just be a nop. try { // Find out how the async operation completed. It must be in a terminal state. bool terminalState = asyncStatus == AsyncStatus.Completed || asyncStatus == AsyncStatus.Canceled || asyncStatus == AsyncStatus.Error; Debug.Assert(terminalState, "The async operation should be in a terminal state."); if (!terminalState) { throw new InvalidOperationException(SR.InvalidOperation_InvalidAsyncCompletion); } // Retrieve the completion data from the IAsyncInfo. TResult result = default(TResult); Exception error = null; if (asyncStatus == AsyncStatus.Error) { error = asyncInfo.ErrorCode; // Defend against a faulty IAsyncInfo implementation: if (error == null) { Debug.Assert(false, "IAsyncInfo.Status == Error, but ErrorCode returns a null Exception (implying S_OK)."); error = new InvalidOperationException(SR.InvalidOperation_InvalidAsyncCompletion); } else { error = asyncInfo.ErrorCode.AttachRestrictedErrorInfo(); } } else if (asyncStatus == AsyncStatus.Completed && getResultsFunction != null) { try { result = getResultsFunction(asyncInfo); } catch (Exception resultsEx) { // According to the WinRT team, this can happen in some egde cases, such as marshalling errors in GetResults. error = resultsEx; asyncStatus = AsyncStatus.Error; } } // Nothing to retrieve for a canceled operation or for a completed operation with no result. // Complete the task based on the previously retrieved results: bool success = false; switch (asyncStatus) { case AsyncStatus.Completed: if (AsyncCausalitySupport.LoggingOn) { AsyncCausalitySupport.TraceOperationCompletedSuccess(this.Task); } success = base.TrySetResult(result); break; case AsyncStatus.Error: Debug.Assert(error != null, "The error should have been retrieved previously."); success = base.TrySetException(error); break; case AsyncStatus.Canceled: success = base.TrySetCanceled(_ct.IsCancellationRequested ? _ct : new CancellationToken(true)); break; } Debug.Assert(success, "Expected the outcome to be successfully transfered to the task."); } catch (Exception exc) { // This really shouldn't happen, but could in a variety of misuse cases // such as a faulty underlying IAsyncInfo implementation. Debug.Assert(false, string.Format("Unexpected exception in Complete: {0}", exc.ToString())); if (AsyncCausalitySupport.LoggingOn) { AsyncCausalitySupport.TraceOperationCompletedError(this.Task); } // For these cases, store the exception into the task so that it makes its way // back to the caller. Only if something went horribly wrong and we can't store the exception // do we allow it to be propagated out to the invoker of the Completed handler. if (!base.TrySetException(exc)) { Debug.Assert(false, "The task was already completed and thus the exception couldn't be stored."); throw; } } } finally { // We may be called on an STA thread which we don't own, so make sure that the RCW is released right // away. Otherwise, if we leave it up to the finalizer, the apartment may already be gone. if (Marshal.IsComObject(asyncInfo)) { Marshal.ReleaseComObject(asyncInfo); } } } // private void Complete(..)
internal override void ProcessConcreteCompletedOperation(IAsyncInfo completedOperation, out Int64 bytesCompleted) { ProcessConcreteCompletedOperation((IAsyncOperation <Boolean>)completedOperation, out bytesCompleted); }
internal override void ProcessConcreteCompletedOperation(IAsyncInfo completedOperation, out Int64 bytesCompleted) { ProcessConcreteCompletedOperation((IAsyncOperationWithProgress <UInt32, UInt32>)completedOperation, out bytesCompleted); }
public static IDisposable AsDisposable(this IAsyncInfo asyncInfo) { return(Disposable.Create(asyncInfo, _ => _.Cancel())); }
internal void StreamOperationCompletedCallback(IAsyncInfo completedOperation, AsyncStatus unusedCompletionStatus) { try { if (_callbackInvoked) throw new InvalidOperationException(SR.InvalidOperation_MultipleIOCompletionCallbackInvocation); _callbackInvoked = true; // This happens in rare stress cases in Console mode and the WinRT folks said they are unlikely to fix this in Dev11. // Moreover, this can happen if the underlying WinRT stream has a faulty user implementation. // If we did not do this check, we would either get the same exception without the explaining message when dereferencing // completedOperation later, or we will get an InvalidOperation when processing the Op. With the check, they will be // aggregated and the user will know what went wrong. if (completedOperation == null) throw new NullReferenceException(SR.NullReference_IOCompletionCallbackCannotProcessNullAsyncInfo); _completedOperation = completedOperation; // processCompletedOperationInCallback == false indicates that the stream is doing a blocking wait on the waitHandle of this IAsyncResult. // In that case calls on completedOperation may deadlock if completedOperation is not free threaded. // By setting processCompletedOperationInCallback to false the stream that created this IAsyncResult indicated that it // will call ProcessCompletedOperation after the waitHandle is signalled to fetch the results. if (_processCompletedOperationInCallback) ProcessCompletedOperation(); } catch (Exception ex) { _bytesCompleted = 0; _errorInfo = ExceptionDispatchInfo.Capture(ex); } finally { _completed = true; Interlocked.MemoryBarrier(); // From this point on, AsyncWaitHandle would create a handle that is readily set, // so we do not need to check if it is being produced asynchronously. if (_waitHandle != null) _waitHandle.Set(); } if (_userCompletionCallback != null) _userCompletionCallback(this); }
protected MulticastAsyncBase(IAsyncInfo wrapped) { this.wrapped = wrapped ?? throw new ArgumentNullException(nameof(wrapped)); }
private void Done(IAsyncInfo info, AsyncStatus status, bool initial) { var error = default(Exception); var result = default(TResult); // // Initial interactions with the IAsyncInfo object. Those could fail, which indicates // a rogue implementation. Failure is just propagated out. // switch (status) { case AsyncStatus.Error: error = info.ErrorCode; if (error == null) { throw new InvalidOperationException("The asynchronous operation failed with a null error code."); } break; case AsyncStatus.Canceled: error = new OperationCanceledException(); break; case AsyncStatus.Completed: if (_getResult != null) { result = _getResult(info); } break; default: if (!initial) { throw new InvalidOperationException("The asynchronous operation completed unexpectedly."); } _onCompleted(info, (iai, s) => Done(iai, s, false)); return; } // // Close as early as possible, before running continuations which could fail. In case of // failure above, we don't close out the object in order to allow for debugging of the // rogue implementation without losing state prematurely. Notice _getResults is merely // an indirect call to the appropriate GetResults method, which is not supposed to throw. // Instead, an Error status should be returned. // info.Close(); // // Now we run the continuations, which could take a long time. Failure here is catastrophic // and under control of the upstream subscriber. // if (error != null) { _subject.OnError(error); } else { if (_getResult != null) { _subject.OnNext(result); } _subject.OnCompleted(); } }
private void Complete(IAsyncInfo asyncInfo, Func <IAsyncInfo, TResult> getResultsFunction, AsyncStatus asyncStatus) { if (asyncInfo == null) { throw new ArgumentNullException(nameof(asyncInfo)); } // TODO: AsyncCausality? try { Debug.Assert(asyncInfo.Status == asyncStatus, "asyncInfo.Status does not match asyncStatus; are we dealing with a faulty IAsyncInfo implementation?"); if (Task.IsCompleted) { Debug.Fail("Expected the task to not yet be completed."); throw new InvalidOperationException("The asynchronous operation could not be completed."); } // Clean up our registration with the cancellation token, noting that we're now in the process of cleaning up. CancellationTokenRegistration ctr; lock (this) { _completing = true; ctr = _ctr; _ctr = default; } ctr.Dispose(); try { if (asyncStatus != AsyncStatus.Completed && asyncStatus != AsyncStatus.Canceled && asyncStatus != AsyncStatus.Error) { Debug.Fail("The async operation should be in a terminal state."); throw new InvalidOperationException("The asynchronous operation could not be completed."); } TResult result = default(TResult); Exception error = null; if (asyncStatus == AsyncStatus.Error) { error = asyncInfo.ErrorCode; // Defend against a faulty IAsyncInfo implementation if (error is null) { Debug.Fail("IAsyncInfo.Status == Error, but ErrorCode returns a null Exception (implying S_OK)."); error = new InvalidOperationException("The asynchronous operation could not be completed."); } } else if (asyncStatus == AsyncStatus.Completed && getResultsFunction != null) { try { result = getResultsFunction(asyncInfo); } catch (Exception resultsEx) { // According to the WinRT team, this can happen in some egde cases, such as marshalling errors in GetResults. error = resultsEx; asyncStatus = AsyncStatus.Error; } } // Complete the task based on the previously retrieved results: bool success = false; switch (asyncStatus) { case AsyncStatus.Completed: // TODO: AsyncCausality? success = base.TrySetResult(result); break; case AsyncStatus.Error: Debug.Assert(error != null, "The error should have been retrieved previously."); success = base.TrySetException(error); break; case AsyncStatus.Canceled: success = base.TrySetCanceled(_ct.IsCancellationRequested ? _ct : new CancellationToken(true)); break; } Debug.Assert(success, "Expected the outcome to be successfully transfered to the task."); } catch (Exception exc) { Debug.Fail($"Unexpected exception in Complete: {exc}"); // TODO: AsyncCausality if (!base.TrySetException(exc)) { Debug.Fail("The task was already completed and thus the exception couldn't be stored."); throw; } } } finally { // We may be called on an STA thread which we don't own, so make sure that the RCW is released right // away. Otherwise, if we leave it up to the finalizer, the apartment may already be gone. if (ComWrappersSupport.TryUnwrapObject(asyncInfo, out var objRef)) { objRef.Dispose(); } } }
internal abstract void ProcessConcreteCompletedOperation(IAsyncInfo completedOperation, out long bytesCompleted);
internal override void ProcessConcreteCompletedOperation(IAsyncInfo completedOperation, out long bytesCompleted) { ProcessConcreteCompletedOperation((IAsyncOperationWithProgress <uint, uint>)completedOperation, out bytesCompleted); }
internal abstract void ProcessConcreteCompletedOperation(IAsyncInfo completedOperation, out Int64 bytesCompleted);
internal override void ProcessConcreteCompletedOperation(IAsyncInfo completedOperation, out Int64 bytesCompleted) { ProcessConcreteCompletedOperation((IAsyncOperationWithProgress<UInt32, UInt32>)completedOperation, out bytesCompleted); }
internal override void ProcessConcreteCompletedOperation(IAsyncInfo completedOperation, out long bytesCompleted) { ProcessConcreteCompletedOperation((IAsyncOperation <bool>)completedOperation, out bytesCompleted); }
internal void CloseStreamOperation() { try { if (_asyncStreamOperation != null) _asyncStreamOperation.Close(); } catch { } _asyncStreamOperation = null; }