在 ViewModel 中调用的异步方法导致死锁

Async method that calls in ViewModel causes deadlock

我向 Github Api 发出请求,所以我有异步方法,这些方法可以完成这项工作。在此之前,我总是在方法中调用它们,从命令(实际上是 DelegateCommand)调用。但现在我想在 ViewModel 中做请求,因为我需要在页面上显示列表。我正在使用 Prism 连接视图和视图模型。 因为我不能使视图模型异步,所以我不能使用等待词,所以我尝试做一些事情,比如从任务中获取结果,或者 task.wait。但是有了这个,我得到了相同的结果。我的应用程序停止在请求时以白色显示工作。我阅读了一些相关信息,我知道在非异步方法中调用异步方法是不好的,它会导致死锁,但我不知道该怎么做。而且我认为死锁导致应用程序停止工作。 这是应用死机的方法:

public async Task<IEnumerable<RepositoryModel>> GetRepositoriesAsync()
{
    try
    {
        var reposRequest = new RepositoryRequest { Sort = RepositorySort.FullName };
        var gitHubRepos = await _gitHubClient.Repository.GetAllForCurrent(reposRequest);  //async request, don't say about name convention, it is not my method.
        var gitRemoteRepos = new List<RepositoryModel>();
        foreach ( var repository in gitHubRepos )
        {
            var repos = new RepositoryModel();
            repos.RepositoryTypeIcon = GetRepositoryTypeIcon(repository);
            gitRemoteRepos.Add(repos);
        }
        return gitRemoteRepos;
    }
    catch ( WebException ex )
    {
        throw new Exception("Something wrong with internet connection, try to On Internet " + ex.Message);
    }
    catch ( Exception ex )
    {
        throw new Exception("Getting repos from github failed! " + ex.Message);
    }
}

这是视图模型:

public class RepositoriesPageViewModel : BindableBase
{
    private INavigationService _navigationService;
    private readonly Session _session;
    public ObservableCollection<RepositoryModel> Repositories { get; }
    private readonly RepositoriesManager _repositoriesManager;
    public RepositoriesPageViewModel(INavigationService navigationService, ISecuredDataProvider securedDataProvider)
    {
        _navigationService = navigationService;
        var token = securedDataProvider.Retreive(ConstantsService.ProviderName, UserManager.GetLastUser());
        _session = new Session(UserManager.GetLastUser(), token.Properties.First().Value);
        var navigationParameters = new NavigationParameters { { "Session", _session } };

        _repositoriesManager = new RepositoriesManager(_session);
        var task = _repositoriesManager.GetRepositoriesAsync();
        //task.Wait();
        Repositories = task.Result as ObservableCollection<RepositoryModel>;
    }
}

我建议使用我的 NotifyTask<T> type, which provides a data-bindable wrapper around Task<T>. I explain this pattern more completely in my article on async MVVM data binding

public class RepositoriesPageViewModel : BindableBase
{
  private INavigationService _navigationService;
  private readonly Session _session;
  public NotifyTask<ObservableCollection<RepositoryModel>> Repositories { get; }
  private readonly RepositoriesManager _repositoriesManager;
  public RepositoriesPageViewModel(INavigationService navigationService, ISecuredDataProvider securedDataProvider)
  {
    _navigationService = navigationService;
    var token = securedDataProvider.Retreive(ConstantsService.ProviderName, UserManager.GetLastUser());
    _session = new Session(UserManager.GetLastUser(), token.Properties.First().Value);
    var navigationParameters = new NavigationParameters { { "Session", _session } };

    _repositoriesManager = new RepositoriesManager(_session);
    Repositories = NotifyTask.Create(GetRepositoriesAsync());
  }
}

private async Task<ObservableCollection<RepositoryModel>> GetRepositoriesAsync()
{
  return new ObservableCollection<RepositoryModel>(await _repositoriesManager.GetRepositoriesAsync());
}

请注意,使用这种方法,您的数据绑定将使用 Repositories.Result 来访问实际集合。其他属性也可用,最值得注意的是 Repositories.IsCompletedRespositories.IsNotCompleted 用于 showing/hiding 个忙碌的微调器。