문제

메모:이 질문의 코드는 일부입니다 Desleeper 전체 소스를 원한다면.

내가 명령에서 벗어난 것 중 하나는 비동기 작업을위한 구운 디자인이었습니다. 명령이 실행되는 동안 버튼이 비활성화되기를 원했고 완료되면 돌아 오기를 원했습니다. 실제 작업이 ThreadPool 작업 항목에서 수행되기를 원했습니다. 마지막으로, 나는 비동기 처리 중에 발생한 오류를 처리하는 방법을 원했습니다.

내 해결책은 Asynccomand입니다.

public abstract class AsyncCommand : ICommand
{
    public event EventHandler CanExecuteChanged;
    public event EventHandler ExecutionStarting;
    public event EventHandler<AsyncCommandCompleteEventArgs> ExecutionComplete;

    public abstract string Text { get; }
    private bool _isExecuting;
    public bool IsExecuting
    {
        get { return _isExecuting; }
        private set
        {
            _isExecuting = value;
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
        }
    }

    protected abstract void OnExecute(object parameter);

    public void Execute(object parameter)
    {   
        try
        {
            IsExecuting = true;
            if (ExecutionStarting != null)
                ExecutionStarting(this, EventArgs.Empty);

            var dispatcher = Dispatcher.CurrentDispatcher;
            ThreadPool.QueueUserWorkItem(
                obj =>
                {
                    try
                    {
                        OnExecute(parameter);
                        if (ExecutionComplete != null)
                            dispatcher.Invoke(DispatcherPriority.Normal, 
                                ExecutionComplete, this, 
                                new AsyncCommandCompleteEventArgs(null));
                    }
                    catch (Exception ex)
                    {
                        if (ExecutionComplete != null)
                            dispatcher.Invoke(DispatcherPriority.Normal, 
                                ExecutionComplete, this, 
                                new AsyncCommandCompleteEventArgs(ex));
                    }
                    finally
                    {
                        dispatcher.Invoke(DispatcherPriority.Normal, 
                            new Action(() => IsExecuting = false));
                    }
                });
        }
        catch (Exception ex)
        {
            IsExecuting = false;
            if (ExecutionComplete != null)
                ExecutionComplete(this, new AsyncCommandCompleteEventArgs(ex));
        }
    }

    public virtual bool CanExecute(object parameter)
    {
        return !IsExecuting;
    }
}

그래서 문제는 다음과 같습니다.이 모든 것이 필요합니까? 데이터 바인딩에 대한 비동기 지원으로 내장 된 것을 알았으므로 명령 실행이 아닌 이유는 무엇입니까? 아마도 그것은 매개 변수 질문과 관련이 있으며, 이것은 나의 다음 질문입니다.

도움이 되었습니까?

해결책

원래 샘플을 다듬을 수 있었고 비슷한 상황에 처해있는 다른 사람에게 조언을 할 수있었습니다.

먼저, 배경 노동자가 필요를 충족시킬 것인지 고려하십시오. 나는 여전히 AsyncCommand를 사용하여 자동 비활성화 기능을 얻지 만 배경 작업자와 함께 많은 일을 수행 할 수 있다면.

그러나 AsyncCommand는 BackgroundWorker를 포장함으로써 비동기 동작과 같은 기능과 같은 명령을 제공합니다 (또한 이 주제에 대한 블로그 항목)

public abstract class AsyncCommand : ICommand
{
    public event EventHandler CanExecuteChanged;
    public event EventHandler RunWorkerStarting;
    public event RunWorkerCompletedEventHandler RunWorkerCompleted;

    public abstract string Text { get; }
    private bool _isExecuting;
    public bool IsExecuting
    {
        get { return _isExecuting; }
        private set
        {
            _isExecuting = value;
            if (CanExecuteChanged != null)
                CanExecuteChanged(this, EventArgs.Empty);
        }
    }

    protected abstract void OnExecute(object parameter);

    public void Execute(object parameter)
    {   
        try
        {   
            onRunWorkerStarting();

            var worker = new BackgroundWorker();
            worker.DoWork += ((sender, e) => OnExecute(e.Argument));
            worker.RunWorkerCompleted += ((sender, e) => onRunWorkerCompleted(e));
            worker.RunWorkerAsync(parameter);
        }
        catch (Exception ex)
        {
            onRunWorkerCompleted(new RunWorkerCompletedEventArgs(null, ex, true));
        }
    }

    private void onRunWorkerStarting()
    {
        IsExecuting = true;
        if (RunWorkerStarting != null)
            RunWorkerStarting(this, EventArgs.Empty);
    }

    private void onRunWorkerCompleted(RunWorkerCompletedEventArgs e)
    {
        IsExecuting = false;
        if (RunWorkerCompleted != null)
            RunWorkerCompleted(this, e);
    }

    public virtual bool CanExecute(object parameter)
    {
        return !IsExecuting;
    }
}

다른 팁

내가 당신의 다른 질문에서 대답했듯이, 당신은 아마도 이것에 동기식으로 바인딩하고 명령을 비동기 적으로 시작하고 싶을 것입니다. 그렇게하면 지금 겪고있는 문제를 피합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top