C# 命令停止执行

C# 命令停止执行,c#,.net,wpf,mvvm,mvvm-light,C#,.net,Wpf,Mvvm,Mvvm Light,我正在制作一个小型MVVM应用程序。它应该接受一个充满Func的类,并显示一个按钮列表,每个按钮执行一个包含Func的命令,并在另一个列表中显示其返回值 该程序一开始运行良好,但在随机按下大量按钮后,它就会停止执行命令。用户界面仍然响应良好。就好像装订断了似的 类有点太多了,所以我在下面的链接中附加了整个项目: 相关代码: namespace AdapterTester.ViewModel { public class MainViewModel : ViewModelBase {

我正在制作一个小型MVVM应用程序。它应该接受一个充满
Func
的类,并显示一个按钮列表,每个按钮执行一个包含
Func
的命令,并在另一个列表中显示其返回值

该程序一开始运行良好,但在随机按下大量按钮后,它就会停止执行命令。用户界面仍然响应良好。就好像装订断了似的

类有点太多了,所以我在下面的链接中附加了整个项目:

相关代码:

namespace AdapterTester.ViewModel
{
  public class MainViewModel : ViewModelBase
  {
    public ObservableCollection<ViewableRelayCommand> CommandsList { get; set; }
    public ObservableCollection<string> Log { get; set; }

    /// <summary>
    /// Initializes a new instance of the MainViewModel class.
    /// </summary>
    public MainViewModel()
    {
      CommandsList = new ObservableCollection<ViewableRelayCommand>();
      Log = new ObservableCollection<string>();
      MapCommands();
    }

    /// <summary>
    /// adds a ViewableRelayCommand to the CommandsList
    /// </summary>
    public void Add(Func<string> iCommand, string CommandName, Func<bool> CanExecute = null)
    {
      CommandsList.Add(new ViewableRelayCommand()
      {
        Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName  + "\n"  + (iCommand.Invoke())); }),
        CommandName = CommandName
      });
    }

    /// <summary>
    /// For Each Func<string> in TestFunctions create a ViewableRelayCommand
    /// </summary>
    private void MapCommands()
    {
      var target = new TestFunctions();
      var methods = target.GetType().GetMethods().Where(m => m.DeclaringType == typeof(TestFunctions));
      foreach (var method in methods)
      {
        if( (method.ReturnType == typeof(string)) && (method.GetParameters().Length ==0))
        {
          Func<string> func = (Func<string>)Delegate.CreateDelegate(typeof(Func<string>), target, method);
          Add(func, method.Name);
        }
      }
    }
  }

  public class ViewableRelayCommand : ViewModelBase
  {
    public RelayCommand Command { get; set; }

    /// <summary>
    /// The <see cref="CommandName" /> property's name.
    /// </summary>
    public const string CommandNamePropertyName = "CommandName";

    private string _CommandName = "Hello";

    /// <summary>
    /// Sets and gets the CommandName property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public string CommandName
    {
      get
      {
        return _CommandName;
      }

      set
      {
        if (_CommandName == value)
        {
          return;
        }

        RaisePropertyChanging(CommandNamePropertyName);
        _CommandName = value;
        RaisePropertyChanged(CommandNamePropertyName);
      }
    }
  }
}
对这样的事情:

List<Action> actions = new List<Action>();
public void Add(Func<string> iCommand, string CommandName, Func<bool> CanExecute = null)
{
    Action act = () => { Log.Insert(0, "-------------\n" + CommandName + "\n" + (iCommand.Invoke())); };
    actions.Add(act);
    CommandsList.Add(new ViewableRelayCommand()
    {
        Command = new RelayCommand(act)
        ,
        CommandName = CommandName
    });
}
List actions=new List();
public void Add(Func-iCommand,string-CommandName,Func-CanExecute=null)
{
Action act=()=>{Log.Insert(0,-----------\n“+CommandName+”\n“+(iCommand.Invoke());};
添加(act);
添加(新的可视RelayCommand()
{
命令=新的中继命令(act)
,
CommandName=CommandName
});
}
因为添加到中继命令的操作没有根

更新更改为我自己的中继命令有帮助。虽然支持Funcs没有

Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName  + "\n"  + (Command.Invoke())); })
改为:

Command = new RelayCommand(() => { Log.Insert(0, "-------------\n"); })

它可以工作,但我不知道为什么不能在Lambda表达式中使用参数(Command和CommandName)?

您从命令中调用命令对吗

 Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName  + "\n"  + (Command.Invoke())); })
这不是递归的吗

能否尝试从表达式中删除调用?
为什么要从内部调用它?

是否使用MVVMLight中的RelayCommand

如果是这样,您可能会遇到GC问题。RelayCommand在内部对其回调使用弱引用

如果您传入的anon函数不是根在其他地方,那么当GC运行时,它可能会被清除

大多数情况下,这不是问题,因为func是对VM的回调,而VM本身的根位于DataContext、ViewModelLocator或其他地方。如果您创建的Func不是根函数,那么这可能是一个问题


根目录这些Func的一种方法是在ViewModel中有一个
列表
,并在创建RelayCommand的同时将它们添加到列表中。

修改绑定跟踪级别,如本例所示:并告诉我们,关于该绑定的调试输出是什么。第一次加载后没有任何变化。很抱歉,现在说不。我在编译你的代码时遇到问题,可能是因为你使用了Blend,而我没有?您是否在
命令
内容
绑定上设置了
TraceLevel=High
?输出建议为
CommandName
打印详细信息。但我们要调试的是
命令
。@rook我没有混合。我刚刚使用了mvvm灯光模板。我确实看到按钮停止工作几分钟后,一个线程停止运行,不知道使用C threadno,左边的命令是ViewableRelayCommand参数。右边的命令是Add函数参数。这是一个糟糕的命名,仅此而已。或者让你知道原因的正确性,但是支持使用funcs而不是funcs创建操作的根:)是的,当然,很好这是因为WeakFunc/Action实际上打开了原始func并将值存储在WeakReferences中。
Command = new RelayCommand(() => { Log.Insert(0, "-------------\n"); })
 Command = new RelayCommand(() => { Log.Insert(0, "-------------\n" + CommandName  + "\n"  + (Command.Invoke())); })