使用异步任务调用同步WCF服务[英] Using asynchronous tasks to call synchronous WCF service

本文是小编为大家收集整理的关于使用异步任务调用同步WCF服务的处理方法,想解了使用异步任务调用同步WCF服务的问题怎么解决?使用异步任务调用同步WCF服务问题的解决办法?使用异步任务调用同步WCF服务问题的解决方案?那么可以参考本文帮助大家快速定位并解决问题,译文如有不准确的地方,大家可以切到English参考源文内容。

问题描述

我有一个由服务客户端拨打的WCF服务.我想使用异步/等待构造来包装呼叫;但是,服务和服务客户​​端为.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);

推荐答案

添加服务参考时,有一个选项可以生成操作的异步版本.

这是(较旧的)APM模式(IASYNCRESULT,BEGINMETHOD,ENDMETHOD).您可以将其连接到异步/等待 fromAsync :

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

当您有很多电话时,这会更好,它不会浪费太多的线程等待I/O.

其他推荐答案

在您的问题中,您首先说明您的客户端已在.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博客发帖有帮助.

其他推荐答案

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

正确的代码看起来像这样:

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://www.itbaoku.cn/post/301045.html

问题描述

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

推荐答案

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.

其他推荐答案

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.

其他推荐答案

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;
}
查看更多