我在异步编程方面有点吃力。我想要一个 viewModel 中的选择触发另一个 ViewModel 中的异步 HttpRequest。但是,它似乎不起作用,我认为这是因为同步事件正在调用异步方法。我知道从上到下使用异步方法是最佳实践。
在下面的代码中,用户在 ProjectsView 中进行选择。这会触发一个 RelayCommand(也许这应该是异步的),它会触发一个事件 Action。 Main ViewModel 侦听此事件,并将选定的项目传递给 SearchViewModel。 ViewModel 调用 SearchViewModel 中的异步方法,发出 HTTP 请求。这就是我的代码似乎总是卡在等待中的地方。
public class ProjectsViewModel : BindableBase
{
public RelayCommand<Project> SelectProjectCommand { get; private set; }
public event Action<Project> SelectProjectRequested = delegate { };
public ProjectsViewModel()
{
SelectProjectCommand = new RelayCommand<Project>(SelectProject);
}
private void SelectProject(Project project)
{
SelectProjectRequested(project);
}
}
public class ViewModel
{
public ViewModel()
{
_projectsViewModel.SelectProjectRequested += InitializeSearchView;
}
private async void InitializeSearchView(Project project)
{
if (project != null)
{
await SearchViewModel.GetAllMaterialsForProjectAsync(project);
}
}
}
public class SearchViewModel : BindableBase
{
public async Task GetAllMaterialsForProjectAsync(Project project)
{
HttpRequestMessage msg = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(HttpClientInstance.BaseUri + "materials/get-materials-for-project/")
};
msg.Headers.Add("projectID", $"{project.Id}");
string responseString = null;
try
{
HttpResponseMessage responseMessage = await HttpClientInstance.httpClient.SendAsync(msg);
responseMessage.EnsureSuccessStatusCode();
responseString = await responseMessage.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
if (responseString != null)
{
List<WindowEntity> windows = DeserializeMaterials(responseString);
Windows = new ObservableCollection<WindowEntity>(windows);
}
}
}
在 HTTP 请求中,有几个线程正在等待。似乎什么都没有发生。然后得到一个异常,但它只是说“任务被取消”
我猜这与同步事件操作触发的异步方法有关。或者它可能与 async void 方法有关。我不太确定。有更好的方法吗?
有人建议使用 Mvvm Toolkit 的 messenger 类 在 viewModels 之间进行通信,但这实际上不能用我的堆栈编译。我遇到了疯狂的参考问题。