0

我有一个由服务客户端调用的 WCF 服务。我想使用 async / await 构造来包装对此的调用;但是,服务和服务客户​​端是.NET3.5。我对此的解决方案如下:

private async Task<ObservableCollection<MyEntity>> LoadData(ParamData param)
{
        ServiceClient svc = new ServiceClient();
        int results = 0;

        // Set-up parameters
        myParams = BuildParams(param);

        // Call a count function to see how much data we're talking about
        // This call should be relatively quick
        var counter = Task.Factory.StartNew(() =>
        {
            results = svc.GetResultCount(myParams);
        }).ContinueWith((task) =>
        {
            if (results <= 10000 ||
                (MessageBox.Show("More than 10000 results, still retrieve data?"), MessageBoxButton.YesNo) == MessageBoxResult .Yes))
            {
                return svc.Search(myParams);
            }
        });
}

我得到编译错误:

Since 'System.Action<System.Threading.Tasks.Task>' returns void, a return keyword must not be followed by an object expression

所以,我的问题是,是否可以以这种方式运行同步方法,如果可以,我做错了什么?我的目标是可以像这样调用该方法:

var data = await LoadData(params);
4

3 回答 3

6

添加服务参考时,可以选择生成操作的异步版本。

这是(较旧的)APM 模式(IAsyncResult、BeginMethod、EndMethod)。您可以使用FromAsync将其挂钩到异步/等待中:

 var task = Task.Factory.FromAsync(BeginGetResultCount, EndGetResultCount, myParams);

当您有很多调用时,这会更好,它不会浪费太多线程来等待 I/O。

于 2013-09-19T09:27:59.837 回答
1

在您的问题中,您首先声明您的客户端在 .NET 3.5 上,然后您继续使用一种async方法并将您的问题标记为 .NET 4.5。所以我假设您实际上是在 .NET 4.5 上运行。

在这种情况下,您可以告诉 svcutil 创建基于任务的异步 API(在 VS2012 中,默认情况下应该这样做),然后像这样调用它们:

private async Task<ObservableCollection<MyEntity>> LoadData(ParamData param)
{
    ServiceClient svc = new ServiceClient();

    // Set-up parameters
    myParams = BuildParams(param);

    // Call a count function to see how much data we're talking about
    // This call should be relatively quick
    var results = await svc.GetResultCountAsync(myParams);
    if (results <= 10000 ||
        (MessageBox.Show("More than 10000 results, still retrieve data?"), MessageBoxButton.YesNo) == MessageBoxResult .Yes))
        return await svc.Search(myParams);
}

如果您实际上使用的是 .NET 4.0,那么 Henk 有正确的答案。在这种情况下,您可能会发现我的asyncWCF 博客文章很有帮助。

于 2013-09-19T12:21:30.197 回答
0

好的 - 我已经解决了这个问题。return 语句从任务返回,而不是从函数返回;这就是它抱怨的原因。

正确的代码如下所示:

private async Task<ObservableCollection<MyEntity>> LoadData(ParamData param)
{
    ServiceClient svc = new ServiceClient();
    int results = 0;

    // Set-up parameters
    myParams = BuildParams(param);

    // Call a count function to see how much data we're talking about
    // This call should be relatively quick
    var counter = Task.Factory.StartNew(() =>
    {
        results = svc.GetResultCount(myParams);
    });

    var returnTask = counter.ContinueWith((task) =>
    {
        if (results <= 10000 ||
            (MessageBox.Show("More than 10000 results, still retrieve data?"), MessageBoxButton.YesNo) == MessageBoxResult .Yes))
        {
            return svc.Search(myParams);
        }
    });

    return returnTask.Result;
}
于 2013-09-19T08:47:01.657 回答