1

我正在使用 WCF 服务在 WPF 应用程序中加载一些数据,直到最近,我还通过 Visual Studio 为我自动生成的基于事件的异步方法来加载:

//Old way
private void LoadFoos(int barId)
{
    serviceClient.SelectFoosByBarIdCompleted += (s, e) =>
    {
        Foos = e.Result.OrderBy(f => f.Description).ToList();
    });
    serviceClient.SelectFoosByBarIdAsync();
}

无论出于何种原因,我们开始使用任务,我对做同样事情的最佳方式有疑问:

//New way
private async void LoadFoos(int barId)
{
    private TaskScheduler uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
    serviceClient.SelectFoosByBarIdAsync(barId).ContinueWith(t => 
    {
        Foos = t.Result.OrderBy(f => f.Description).ToList();
    }, uiTaskScheduler);
}

我认为这更难看,因为我必须手动设置上下文,所以我不会在错误的线程上更新内容(Foos是数据绑定属性)。另外,我认为我可以做到这一点:

//New way #2, doesn't sort ;(
private async void LoadFoos(int barId)
{
    private TaskScheduler uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
    var selectFoosTask = serviceClient.SelectFoosByBarIdAsync(barId);
    Foos = selectFoosTask;
}

但是我不能根据Description.

整个任务概念对我来说相当新,所以也许我遗漏了一些东西。有没有比我上面列出的更简洁的方法?

4

3 回答 3

1

您将只使用等待,而不是继续:

private async Task LoadFoos(int barId)
{
    var temp = await serviceClient.SelectFoosByBarIdAsync(barId);

    Foos = temp.OrderBy(f => f.Description).ToList();
}

请注意,使用 async void,甚至只是一个Task返回方法可能并不理想。将其重写为(*假设 Foos 是 a List<string>)可能会更好:

private async Task<List<string>> LoadFoosAsync(int barId)
{
    var temp = await serviceClient.SelectFoosByBarIdAsync(barId);
    return temp.OrderBy(f => f.Description).ToList();
}

然后,当你调用它时,使用:

Foos = await LoadFoosAsync(id);
于 2013-10-10T18:30:37.010 回答
1

至于将基于事件的异步方法转换为基于任务的方法(顺便说一下,任务非常出色:))查看这些博客文章

http://msdn.microsoft.com/en-us/magazine/ff959203.aspx http://blogs.msdn.com/b/pfxteam/archive/2009/06/19/9791857.aspx

在编组回 ui 线程之前,您仍然可以完成所有处理。您还可以创建自己的 ContinueWith 辅助方法,将任务放在正确的 TaskScheduler 上。(如果你不能使用 await,这是最简单的选择)

另请注意,wsdl 工具的较新版本(我认为是 2012 年及更高版本)实际上会为服务生成基于任务的异步方法。

于 2013-10-10T18:34:22.180 回答
0

由于该方法async只是await任务而不是手动添加延续:

private async Task LoadFoos(int barId)
{
    Foos = (await serviceClient.SelectFoosByBarIdAsync(barId))
        .OrderBy(f => f.Description).ToList();
}

另请注意,您应该尽可能避免async void使用方法,因为这样您就无法知道异步操作何时结束,也无法访问引发的任何异常。而是让该方法返回一个Task. 更好的是让方法返回一个返回的数据Task<T>在哪里T,而不是让方法设置其他字段。

于 2013-10-10T18:29:03.587 回答