Пример #1
0
        /// <summary>
        /// Defines the method to be called when the command is invoked.
        /// </summary>
        /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can
        /// be set to null.</param>
        /// <param name="ignoreCanExecuteCheck">if set to <c>true</c>, the check on <see cref="Command{TExecuteParameter, TCanExecuteParameter}.CanExecute()" /> will be used before
        /// actually executing the action.</param>
        protected override async void Execute(TExecuteParameter parameter, bool ignoreCanExecuteCheck)
        {
            // Double check whether execution is allowed, some controls directly call Execute
            if (_execute == null || IsExecuting || (!ignoreCanExecuteCheck && !CanExecute(parameter)))
            {
                return;
            }

            var args = new CommandCanceledEventArgs(parameter);

            Executing.SafeInvoke(this, args);

            if (args.Cancel)
            {
                return;
            }

            if (_cancellationTokenSource != null)
            {
                _cancellationTokenSource.Dispose();
            }
            _cancellationTokenSource = new CancellationTokenSource();

            RaiseCanExecuteChanged();

            var executionTask = _execute(parameter, _cancellationTokenSource.Token, _progress);

            try
            {
                Log.Info("Executing task command...");

                await executionTask.ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                Log.Info("Task was canceled.");
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Task ended with exception.");
            }
            finally
            {
                _cancellationTokenSource.Dispose();
                _cancellationTokenSource = null;
            }

            if (executionTask.IsCanceled || executionTask.IsFaulted)
            {
                Canceled.SafeInvoke(this, new CommandEventArgs(parameter));
            }
            else
            {
                RaiseExecuted(parameter);
            }

            RaiseCanExecuteChanged();
        }
Пример #2
0
        /// <summary>
        /// Defines the method to be called when the command is invoked.
        /// </summary>
        /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
        /// <param name="ignoreCanExecuteCheck">if set to <c>true</c>, the check on <see cref="System.Windows.Input.ICommand.CanExecute"/> will be used before actually executing the action.</param>
        protected override async void Execute(TExecuteParameter parameter, bool ignoreCanExecuteCheck)
        {
            if (IsExecuting)
            {
                return;
            }

            // It might be possible that the IsExecuting is used as a check whether the command can be executed again,
            // so use that as a check
            var canExecute = CanExecute(parameter);

            if (!canExecute)
            {
                return;
            }

            var args = new CommandCanceledEventArgs(parameter);

            Executing.SafeInvoke(this, args);

            if (args.Cancel)
            {
                return;
            }

            IsExecuting = true;

            RaiseCanExecuteChanged();

            // Run the action on a new thread from the thread pool (this will therefore work in Silverlight and Windows Phone as well)
#if NETFX_CORE
            await ThreadPool.RunAsync(state =>
#else
            ThreadPool.QueueUserWorkItem(state =>
#endif
            {
                // Skip the check, we already did that
                base.Execute(parameter, true);

                ReportProgress(() =>
                {
                    IsExecuting = false;

                    if (IsCancelationRequested)
                    {
                        Canceled.SafeInvoke(this, () => new CommandEventArgs(parameter));
                    }
                    else
                    {
                        RaiseExecuted(parameter);
                    }

                    IsCancelationRequested = false;
                });
            });
        }
Пример #3
0
        /// <summary>
        /// Defines the method to be called when the command is invoked.
        /// </summary>
        /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can
        /// be set to null.</param>
        /// <param name="ignoreCanExecuteCheck">if set to <c>true</c>, the check on <see cref="Command{TExecuteParameter, TCanExecuteParameter}.CanExecute()" /> will be used before
        /// actually executing the action.</param>
#pragma warning disable AvoidAsyncVoid
        protected override async void Execute(TExecuteParameter parameter, bool ignoreCanExecuteCheck)
#pragma warning restore AvoidAsyncVoid
        {
            var executeAsync = _executeAsync;

            // Double check whether execution is allowed, some controls directly call Execute
            if (executeAsync is null || IsExecuting || (!ignoreCanExecuteCheck && !CanExecute(parameter)))
            {
                return;
            }

            if (_cancellationTokenSource != null)
            {
                _cancellationTokenSource.Dispose();
            }

            _cancellationTokenSource = new CancellationTokenSource();

            var args = new CommandCanceledEventArgs(parameter);

            Executing?.Invoke(this, args);

            if (args.Cancel)
            {
                return;
            }

            RaiseCanExecuteChanged();

            // Use TaskCompletionSource to create a separate task that will not contain the
            // exception that might be thrown. This allows us to let the users await the task
            // but still respect the SwallowExceptions property
            var tcs = new TaskCompletionSource <object>();

            _task = tcs.Task;

            Task executionTask    = null;
            var  handledException = false;

            try
            {
                Log.Debug("Executing task command");

                executionTask = executeAsync(parameter, _cancellationTokenSource.Token, _progress);
                await executionTask.ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                Log.Debug("Task was canceled");
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Task ended with exception");

                // Important: end the task, the exception thrown below will be earlier than the finally block
                _cancellationTokenSource?.Dispose();
                _cancellationTokenSource = null;

                if (!SwallowExceptions)
                {
                    handledException = true;
                    tcs.TrySetException(ex);
                    throw;
                }
            }
            finally
            {
                _cancellationTokenSource?.Dispose();
                _cancellationTokenSource = null;

                if (!handledException)
                {
                    tcs.TrySetResult(null);
                }
            }

            if (executionTask?.IsCanceled ?? false)
            {
                Canceled?.Invoke(this, new CommandEventArgs(parameter));
            }
            else
            {
                RaiseExecuted(parameter);
            }

            RaiseCanExecuteChanged();
        }
Пример #4
0
        /// <summary>
        /// Defines the method to be called when the command is invoked.
        /// </summary>
        /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can
        /// be set to null.</param>
        /// <param name="ignoreCanExecuteCheck">if set to <c>true</c>, the check on <see cref="Command{TExecuteParameter, TCanExecuteParameter}.CanExecute()" /> will be used before
        /// actually executing the action.</param>
        protected override async Task ExecuteAsync(TExecuteParameter parameter, bool ignoreCanExecuteCheck)
        {
            var executeAsync = _executeAsync;

            // Double check whether execution is allowed, some controls directly call Execute
            if (executeAsync == null || IsExecuting || (!ignoreCanExecuteCheck && !CanExecute(parameter)))
            {
                return;
            }

            if (_cancellationTokenSource != null)
            {
                _cancellationTokenSource.Dispose();
            }

            _cancellationTokenSource = new CancellationTokenSource();

            var args = new CommandCanceledEventArgs(parameter);

            Executing.SafeInvoke(this, args);

            if (args.Cancel)
            {
                return;
            }

            RaiseCanExecuteChanged();

            var executionTask = executeAsync(parameter, _cancellationTokenSource.Token, _progress);

            // Use TaskCompletionSource to create a separate task that will not contain the
            // exception that might be thrown. This allows us to let the users await the task
            // but still respect the SwallowExceptions property
            var tcs = new TaskCompletionSource <object>();

            _task = tcs.Task;

            try
            {
                Log.Debug("Executing task command");

                await executionTask.ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                Log.Debug("Task was canceled");
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Task ended with exception");

                if (!SwallowExceptions)
                {
                    throw;
                }
            }
            finally
            {
                _cancellationTokenSource.Dispose();
                _cancellationTokenSource = null;

                tcs.TrySetResult(null);
                _task = null;
            }

            if (executionTask.IsCanceled)
            {
                Canceled.SafeInvoke(this, () => new CommandEventArgs(parameter));
            }
            else
            {
                await RaiseExecutedAsync(parameter);
            }

            RaiseCanExecuteChanged();
        }