Пример #1
0
        IEnumerator <Task <AsyncCompletedEventArgs> > FetchOperationAsyncHelper(object state, CancellationToken token, int timeout, Action continuator)
        {
            var tcs = new TaskCompletionSource <AsyncCompletedEventArgs>();
            // prepare the timeout
            CancellationToken newToken;

            if (timeout != Timeout.Infinite)
            {
                var cts = CancellationTokenSource.CreateLinkedTokenSource(token);
                TaskExt.CancelAfterEx(cts, timeout * 1000);
                newToken = cts.Token;
            }
            else
            {
                newToken = token;
            }
            /* handle completion */
            AsyncCompletedEventHandler handler = (sender, args) =>
            {
                if (args.Cancelled)
                {
                    tcs.TrySetCanceled();
                }
                else if (args.Error != null)
                {
                    tcs.SetException(args.Error);
                }
                else
                {
                    tcs.SetResult(args);
                }
            };

            this.FetchOperationCompleted += handler;
            try
            {
                using (newToken.Register(() =>
                {
                    try
                    {
                        tcs.SetCanceled();
                    }
                    catch (InvalidOperationException)
                    {
                        /* cancel when already finished, does not matter */
#if DEBUG
                        Tracing.WarningDAL("Canceled async db operation, when it has already completed.");
#endif
                    }
                }, useSynchronizationContext: false))
                {
                    this.StartFetchOperation(state);
                    yield return(tcs.Task.Continuation(continuator));
                }
            }
            finally
            {
                this.FetchOperationCompleted -= handler;
            }
        }