使用异步任务调用同步WCF服务

时间:2013-09-19 08:35:11

标签: c# wcf asynchronous .net-4.5 async-await

我有一个服务客户端调用的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);

3 个答案:

答案 0 :(得分:6)

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

这是(较旧的)APM模式(IAsyncResult,BeginMethod,EndMethod)。您可以使用FromAsync

将其挂钩到异步/等待
 var task = Task.Factory.FromAsync(BeginGetResultCount, EndGetResultCount, myParams);

如果你有很多电话,那就更好了,它不会浪费那么多线程来等待I / O.

答案 1 :(得分: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有正确的答案。在这种情况下,您可能会发现我的async WCF blog post有帮助。

答案 2 :(得分: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;
}