Beispiel #1
0
        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();
 }
Beispiel #3
0
        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;
     }
 }
Beispiel #5
0
        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);
        }
Beispiel #9
0
        /// <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);
 }
Beispiel #17
0
        /// <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);
 }
Beispiel #20
0
 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);
        }
Beispiel #22
0
 protected MulticastAsyncBase(IAsyncInfo wrapped)
 {
     this.wrapped = wrapped ?? throw new ArgumentNullException(nameof(wrapped));
 }
Beispiel #23
0
        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;
 }