سؤال

ملحوظة:الكود الموجود في هذا السؤال جزء من com.deSleeper اذا كنت تريد المصدر كاملا.

أحد الأشياء التي أردتها من الأوامر هو التصميم المخبوز للعمليات غير المتزامنة.كنت أرغب في الضغط على الزر لتعطيله أثناء تنفيذ الأمر، والعودة عند اكتماله.أردت أن يتم تنفيذ العمل الفعلي في عنصر عمل ThreadPool.وأخيرًا، أردت طريقة للتعامل مع أي أخطاء تحدث أثناء المعالجة غير المتزامنة.

كان الحل الخاص بي هو AsyncCommand:

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;
    }
}

لذا فإن السؤال هو:هل كل هذا ضروري؟لقد لاحظت وجود دعم غير متزامن لربط البيانات، فلماذا لا يتم تنفيذ الأمر؟ربما يتعلق الأمر بسؤال المعلمة، وهو سؤالي التالي.

هل كانت مفيدة؟

المحلول

لقد تمكنت من تحسين العينة الأصلية والحصول على بعض النصائح لأي شخص آخر يواجه مواقف مماثلة.

أولاً، فكر في ما إذا كان تطبيق BackgroundWorker سيلبي الاحتياجات أم لا.ما زلت أستخدم AsyncCommand في كثير من الأحيان للحصول على وظيفة التعطيل التلقائي، ولكن إذا كان من الممكن القيام بالعديد من الأشياء باستخدام BackgroundWorker.

ولكن من خلال تغليف تطبيق BackgroundWorker، يوفر AsyncCommand وظيفة تشبه الأوامر مع سلوك غير متزامن (لدي أيضًا دخول بلوق حول هذا الموضوع)

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