.net 为什么此DelegateCommand不能使用后台工作人员正确刷新CanExecute?

.net 为什么此DelegateCommand不能使用后台工作人员正确刷新CanExecute?,.net,wpf,multithreading,backgroundworker,delegatecommand,.net,Wpf,Multithreading,Backgroundworker,Delegatecommand,在WPF中使用DelegateCommand时,我面临以下问题: 如果在UI线程上执行命令,则在后台工作线程中执行命令1会阻止窗口正确刷新按钮的CanExecute。单击按钮外的CanExecute将相应刷新。有什么提示吗 (下面是DelegateCommand的代码,如果太大,很抱歉。据我所知,这是DelegateCommand的常见实现) XAML: } 委派命令C#: 公共类DelegateCommand:ICommand { #区域构造函数 /// ///建造师 /// 公共Dele

在WPF中使用DelegateCommand时,我面临以下问题:

如果在UI线程上执行命令,则在后台工作线程中执行命令1会阻止窗口正确刷新按钮的CanExecute。单击按钮外的CanExecute将相应刷新。有什么提示吗

(下面是DelegateCommand的代码,如果太大,很抱歉。据我所知,这是DelegateCommand的常见实现)

XAML:

}

委派命令C#:

公共类DelegateCommand:ICommand
{
#区域构造函数
/// 
///建造师
/// 
公共DelegateCommand(Action executeMethod)
:此(executeMethod、null、false)
{
}
/// 
///建造师
/// 
公共DelegateCommand(Action executeMethod、Func canExecuteMethod)
:此(executeMethod、canExecuteMethod、false)
{
}
/// 
///建造师
/// 
public DelegateCommand(Action executeMethod、Func canExecuteMethod、bool IsAutomaticCrequeryDisabled)
{
if(executeMethod==null)
{
抛出新ArgumentNullException(“executeMethod”);
}
这._executeMethod=executeMethod;
这._canExecuteMethod=canExecuteMethod;
此._IsAutomaticCrequeryDisabled=IsAutomaticCrequeryDisabled;
}
#端区
#区域公共方法
/// 
///方法来确定是否可以执行该命令
/// 
公共图书馆
{
if(this.\u canExecuteMethod!=null)
{
返回此项。_canExecuteMethod();
}
返回true;
}
/// 
///命令的执行
/// 
public void Execute()
{
if(this.\u executeMethod!=null)
{
这个。_executeMethod();
}
}
/// 
///属性启用或禁用CommandManager对此命令的自动重新查询
/// 
公共图书馆被自动火化禁用
{
得到
{
将此返回。\u自动火化已禁用;
}
设置
{
如果(此.\u为自动火化禁用!=值)
{
如果(值)
{
CommandManagerHelper.RemoveHandlers从建议的查询中删除(此项可执行更改Handlers);
}
其他的
{
建议的CommandManagerHelper.AddHandlerStoreQuerys(此.\u可执行更改Handlers);
}
此._IsAutomaticCrequeryDisabled=值;
}
}
}
/// 
///引发CanExecuteChaged事件
/// 
public void raisecancecutechanged()
{
this.OnCanExecuteChanged();
}
/// 
///用于引发CanExecuteChanged事件的受保护虚拟方法
/// 
受保护的虚拟void OnCanExecuteChanged()
{
CommandManagerHelper.CallWeakReferenceHandlers(此.\u可执行更改句柄);
}
#端区
#区域ICommand成员
/// 
///ICommand.CanExecuteChanged实现
/// 
公共事件事件处理程序CanExecuteChanged
{
添加
{
如果(!此.\已自动火化禁用)
{
CommandManager.RequerySuggested+=值;
}
CommandManagerHelper.AddWeakReferenceHandler(请参阅此文件)_canExecuteChangedHandlers,值,2);
}
去除
{
如果(!此.\已自动火化禁用)
{
CommandManager.RequerySuggested-=值;
}
CommandManagerHelper.RemoveWeakReferenceHandler(此.\u可执行更改句柄,值);
}
}
bool ICommand.CanExecute(对象参数)
{
返回这个。CanExecute();
}
void ICommand.Execute(对象参数)
{
这是Execute();
}
#端区
#区域数据
私有只读操作_executeMethod;
私有只读函数可执行方法;
私人住宅被自动火化禁用;
私有列表\u CanexecuteChangedHandler;
#端区
}
和指挥官经理:

    internal class CommandManagerHelper
{
    internal static void CallWeakReferenceHandlers(List<WeakReference> handlers)
    {
        if (handlers != null)
        {
            // Take a snapshot of the handlers before we call out to them since the handlers
            // could cause the array to me modified while we are reading it.

            EventHandler[] callees = new EventHandler[handlers.Count];
            int count = 0;

            for (int i = handlers.Count - 1; i >= 0; i--)
            {
                WeakReference reference = handlers[i];
                EventHandler handler = reference.Target as EventHandler;
                if (handler == null)
                {
                    // Clean up old handlers that have been collected
                    handlers.RemoveAt(i);
                }
                else
                {
                    callees[count] = handler;
                    count++;
                }
            }

            // Call the handlers that we snapshotted
            for (int i = 0; i < count; i++)
            {
                EventHandler handler = callees[i];
                handler(null, EventArgs.Empty);
            }
        }
    }

    internal static void AddHandlersToRequerySuggested(List<WeakReference> handlers)
    {
        if (handlers != null)
        {
            foreach (WeakReference handlerRef in handlers)
            {
                EventHandler handler = handlerRef.Target as EventHandler;
                if (handler != null)
                {
                    CommandManager.RequerySuggested += handler;
                }
            }
        }
    }

    internal static void RemoveHandlersFromRequerySuggested(List<WeakReference> handlers)
    {
        if (handlers != null)
        {
            foreach (WeakReference handlerRef in handlers)
            {
                EventHandler handler = handlerRef.Target as EventHandler;
                if (handler != null)
                {
                    CommandManager.RequerySuggested -= handler;
                }
            }
        }
    }

    internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler)
    {
        AddWeakReferenceHandler(ref handlers, handler, -1);
    }

    internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
    {
        if (handlers == null)
        {
            handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
        }

        handlers.Add(new WeakReference(handler));
    }

    internal static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
    {
        if (handlers != null)
        {
            for (int i = handlers.Count - 1; i >= 0; i--)
            {
                WeakReference reference = handlers[i];
                EventHandler existingHandler = reference.Target as EventHandler;
                if ((existingHandler == null) || (existingHandler == handler))
                {
                    // Clean up old handlers that have been collected
                    // in addition to the handler that is to be removed.
                    handlers.RemoveAt(i);
                }
            }
        }
    }
}
内部类CommandManagerHelper
{
内部静态void callweakreferencehandler(列表处理程序)
{
if(处理程序!=null)
{
//在调用处理程序之前,请先拍摄处理程序的快照
//可能会导致我们在读取阵列时对其进行修改。
EventHandler[]被调用方=新的EventHandler[handlers.Count];
整数计数=0;
对于(int i=handlers.Count-1;i>=0;i--)
{
WeakReference reference=handlers[i];
EventHandler=reference.Target作为EventHandler;
if(handler==null)
{
//清理已收集的旧处理程序
2.RemoveAt(i);
}
其他的
{
被调用方[计数]=处理程序;
计数++;
}
}
//调用我们拍摄的处理程序
for(int i=0;iusing System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using Utils.Wpf;

namespace BackgroundWorkTest
{
public partial class MainWindow : Window
{
    private bool _canCommand1 = true;
    private bool _canCommand2 = true;

    private readonly BackgroundWorker _backgroundWorker;

    public ICommand Command1 { get; private set; }
    public ICommand Command2 { get; private set; }

    public MainWindow()
    {
        this.Command1 = new DelegateCommand(this.ExecuteCommand1, this.CanCommand1);
        this.Command2 = new DelegateCommand(this.ExecuteCommand2, this.CanCommand2);

        _backgroundWorker = new BackgroundWorker();
        _backgroundWorker.DoWork += _backgroundWorker_DoWork;
        _backgroundWorker.RunWorkerCompleted += _backgroundWorker_RunWorkerCompleted;

        InitializeComponent();

        this.DataContext = this;
    }

    private void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        System.Threading.Thread.Sleep(2000);
    }

    private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        System.Threading.Thread.Sleep(2000);
        _canCommand2 = true;
        _canCommand1 = false;
    }

    private bool CanCommand2()
    {
        return _canCommand2;
    }

    private void ExecuteCommand2()
    {
        _canCommand2 = false;
        _canCommand1 = true;
    }

    private bool CanCommand1()
    {
        return _canCommand1;
    }

    private void ExecuteCommand1()
    {
        _backgroundWorker.RunWorkerAsync();
    }
}
    public class DelegateCommand : ICommand
{
    #region Constructors

    /// <summary>
    ///     Constructor
    /// </summary>
    public DelegateCommand(Action executeMethod)
        : this(executeMethod, null, false)
    {
    }

    /// <summary>
    ///     Constructor
    /// </summary>
    public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
        : this(executeMethod, canExecuteMethod, false)
    {
    }

    /// <summary>
    ///     Constructor
    /// </summary>
    public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
    {
        if (executeMethod == null)
        {
            throw new ArgumentNullException("executeMethod");
        }

        this._executeMethod = executeMethod;
        this._canExecuteMethod = canExecuteMethod;
        this._isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
    }

    #endregion

    #region Public Methods

    /// <summary>
    ///     Method to determine if the command can be executed
    /// </summary>
    public bool CanExecute()
    {
        if (this._canExecuteMethod != null)
        {
            return this._canExecuteMethod();
        }
        return true;
    }

    /// <summary>
    ///     Execution of the command
    /// </summary>
    public void Execute()
    {
        if (this._executeMethod != null)
        {
            this._executeMethod();
        }
    }

    /// <summary>
    ///     Property to enable or disable CommandManager's automatic requery on this command
    /// </summary>
    public bool IsAutomaticRequeryDisabled
    {
        get
        {
            return this._isAutomaticRequeryDisabled;
        }
        set
        {
            if (this._isAutomaticRequeryDisabled != value)
            {
                if (value)
                {
                    CommandManagerHelper.RemoveHandlersFromRequerySuggested(this._canExecuteChangedHandlers);
                }
                else
                {
                    CommandManagerHelper.AddHandlersToRequerySuggested(this._canExecuteChangedHandlers);
                }
                this._isAutomaticRequeryDisabled = value;
            }
        }
    }

    /// <summary>
    ///     Raises the CanExecuteChaged event
    /// </summary>
    public void RaiseCanExecuteChanged()
    {
        this.OnCanExecuteChanged();
    }

    /// <summary>
    ///     Protected virtual method to raise CanExecuteChanged event
    /// </summary>
    protected virtual void OnCanExecuteChanged()
    {
        CommandManagerHelper.CallWeakReferenceHandlers(this._canExecuteChangedHandlers);
    }

    #endregion

    #region ICommand Members

    /// <summary>
    ///     ICommand.CanExecuteChanged implementation
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add
        {
            if (!this._isAutomaticRequeryDisabled)
            {
                CommandManager.RequerySuggested += value;
            }
            CommandManagerHelper.AddWeakReferenceHandler(ref this._canExecuteChangedHandlers, value, 2);
        }
        remove
        {
            if (!this._isAutomaticRequeryDisabled)
            {
                CommandManager.RequerySuggested -= value;
            }
            CommandManagerHelper.RemoveWeakReferenceHandler(this._canExecuteChangedHandlers, value);
        }
    }

    bool ICommand.CanExecute(object parameter)
    {
        return this.CanExecute();
    }

    void ICommand.Execute(object parameter)
    {
        this.Execute();
    }

    #endregion

    #region Data

    private readonly Action _executeMethod;
    private readonly Func<bool> _canExecuteMethod;
    private bool _isAutomaticRequeryDisabled;
    private List<WeakReference> _canExecuteChangedHandlers;

    #endregion
}
    internal class CommandManagerHelper
{
    internal static void CallWeakReferenceHandlers(List<WeakReference> handlers)
    {
        if (handlers != null)
        {
            // Take a snapshot of the handlers before we call out to them since the handlers
            // could cause the array to me modified while we are reading it.

            EventHandler[] callees = new EventHandler[handlers.Count];
            int count = 0;

            for (int i = handlers.Count - 1; i >= 0; i--)
            {
                WeakReference reference = handlers[i];
                EventHandler handler = reference.Target as EventHandler;
                if (handler == null)
                {
                    // Clean up old handlers that have been collected
                    handlers.RemoveAt(i);
                }
                else
                {
                    callees[count] = handler;
                    count++;
                }
            }

            // Call the handlers that we snapshotted
            for (int i = 0; i < count; i++)
            {
                EventHandler handler = callees[i];
                handler(null, EventArgs.Empty);
            }
        }
    }

    internal static void AddHandlersToRequerySuggested(List<WeakReference> handlers)
    {
        if (handlers != null)
        {
            foreach (WeakReference handlerRef in handlers)
            {
                EventHandler handler = handlerRef.Target as EventHandler;
                if (handler != null)
                {
                    CommandManager.RequerySuggested += handler;
                }
            }
        }
    }

    internal static void RemoveHandlersFromRequerySuggested(List<WeakReference> handlers)
    {
        if (handlers != null)
        {
            foreach (WeakReference handlerRef in handlers)
            {
                EventHandler handler = handlerRef.Target as EventHandler;
                if (handler != null)
                {
                    CommandManager.RequerySuggested -= handler;
                }
            }
        }
    }

    internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler)
    {
        AddWeakReferenceHandler(ref handlers, handler, -1);
    }

    internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
    {
        if (handlers == null)
        {
            handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
        }

        handlers.Add(new WeakReference(handler));
    }

    internal static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
    {
        if (handlers != null)
        {
            for (int i = handlers.Count - 1; i >= 0; i--)
            {
                WeakReference reference = handlers[i];
                EventHandler existingHandler = reference.Target as EventHandler;
                if ((existingHandler == null) || (existingHandler == handler))
                {
                    // Clean up old handlers that have been collected
                    // in addition to the handler that is to be removed.
                    handlers.RemoveAt(i);
                }
            }
        }
    }
}