产生的RelayCommand和async方法:"' System.Reflection.TargetInvocationException'发生在mscorlib.dll"

时间:2016-10-12 12:12:34

标签: c# async-await mvvm-light mscorlib

Mvvm light RelayCommand让我对async方法感到头疼。 WPF按钮与以下relayCommand绑定:

    private RelayCommand _importDeviceCommand;
    /// <summary>
    /// Import device button for SelectDeviceView.
    /// </summary>
    public RelayCommand ImportDeviceCommand
    {
        get
        {
            return _importDeviceCommand
                   ?? (_importDeviceCommand = new RelayCommand(async () => await AddDeviceClickExecute(),
                       () => _selectedCableType != null
                             && _selectedAddDevice != null
                             && _selectedPointNames != null 
                             && _selectedPointNames.Any()));
        }
    }

我可能会以某种形式滥用它,因为在方法AddDeviceClickExecute完成后,偶尔会遇到以下异常。

  

未处理的类型异常   &#39; System.Reflection.TargetInvocationException&#39;发生在mscorlib.dll

  • 有哪些可能的解决方案?
  • 是否与lambda方法调用有关?
  • 因此,我怎样才能以这样的方式重构relayCommand 没有使用lambda?

编辑1

调用异步方法,不幸的是,try / catch没有任何区别吗?

private async Task AddDeviceClickExecute()
        {
            _linkTheSocket = true;

            var deviceImporter = new DeviceImporterAsync2(_projectContext, _deviceContext);

            var progress = new Progress<string>(status =>
            {
                _importDeviceProgress = status;
                RaisePropertyChanged("ImportDeviceProgress");
            });

            try
            {
                await deviceImporter.InvokeSimpleDeviceImport(UserSelectedSockets, progress);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Exception during simple device import", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

编辑2

AddDeviceClickExecute退出后立即发生以下异常。

Image of the exception

编辑3

  

原来我使用async和relayCommand的方式了   与我的例外无关。问题得到解决。

1 个答案:

答案 0 :(得分:2)

每当你有一个async void方法的异常转义(即你传递给RelayCommand的lambda)时,你会看到一个未处理的异常。

这是正常和预期的行为;除了RelayCommand包装器之外,它与您从同步TargetInvocationException lambda中看到的行为相同。正如其他人所指出的那样,只需检查InnerException以查看实际的基础异常。

如果你想捕获这些异常,你应该将async void方法的整个主体包裹在try / {{1 }}。这是可能的,但在lambda中有些尴尬:

catch

但是,IMO变得非常尴尬。最好将其拆分为另一种方法:

return _importDeviceCommand
    ?? (_importDeviceCommand = new RelayCommand(async () =>
        { try { await AddDeviceClickExecute(); } catch (Exception ex) { ... } },
      () => _selectedCableType != null
         && _selectedAddDevice != null
         && _selectedPointNames != null 
         && _selectedPointNames.Any()));