Using asynchronous tasks to call synchronous WCF service

自作多情 提交于 2019-12-13 04:35:28

问题


I have a WCF service, called by a service client. I'd like to use the async / await constructs to wrap the call to this; however, the service and service client are .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);

回答1:


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). You can hook this into async/wait with 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.




回答2:


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. So I'm assuming that you are actually running on .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:

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. In that case, you may find my async WCF blog post helpful.




回答3:


Okay - I've solved this. The return statement returns from the task, not the function; 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;
}


来源:https://stackoverflow.com/questions/18889862/using-asynchronous-tasks-to-call-synchronous-wcf-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!