简体   繁体   English

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

[英]Using asynchronous tasks to call synchronous WCF service

I have a WCF service, called by a service client. 我有一个WCF服务,由服务客户端调用。 I'd like to use the async / await constructs to wrap the call to this; 我想使用async / await结构来包装对此的调用; however, the service and service client are .NET3.5. 但是,服务和服务客户​​端是.NET3.5。 My solution to this is as follows: 我对此的解决方案如下:

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);
            }
        });
}

I get the compile error: 我收到编译错误:

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

So, my question is, is it possible to run a synchronous method in this fashion and, if so, what am I doing wrong? 因此,我的问题是,是否可以以此方式运行同步方法?如果是,我在做什么错? My objective is that the method can be called like so: 我的目标是可以像这样调用该方法:

var data = await LoadData(params);

When you add the Service Reference there is an option to generate async versions of the operations. 添加服务参考时,有一个选项可以生成操作的异步版本。

This is the (older) APM pattern (IAsyncResult, BeginMethod, EndMethod). 这是(较旧的)APM模式(IAsyncResult,BeginMethod,EndMethod)。 You can hook this into async/wait with FromAsync : 您可以使用FromAsync将其挂接到异步/等待中:

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

When you have many calls this is better, it doesn't waste so many threads to wait for I/O. 当您有许多调用时,这会更好,它不会浪费太多线程来等待I / O。

In your question, you first state that your client is on .NET 3.5, but then you proceed with an async method and tagged your question .NET 4.5. 在您的问题中,您首先要声明您的客户端在.NET 3.5上,但随后您要使用async方法并标记您的问题.NET 4.5。 So I'm assuming that you are actually running on .NET 4.5. 因此,我假设您实际上是在.NET 4.5上运行。

In that case, you can just tell svcutil to create task-based asynchronous APIs (in VS2012, it should do this by default), and then call them like this: 在这种情况下,您可以告诉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);
}

If you are actually on .NET 4.0, then Henk has the correct answer. 如果你实际上在.NET 4.0,然后亨克具有正确的答案。 In that case, you may find my async WCF blog post helpful. 在这种情况下,您可能会发现我的async WCF博客文章很有帮助。

Okay - I've solved this. 好的-我已经解决了。 The return statement returns from the task, not the function; return语句从任务而不是函数返回; which is why it was complaining. 这就是为什么它抱怨。

The correct code looks like this: 正确的代码如下所示:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM