我如何使用异步/等待调用web服务? [英] How can I use async/await to call a webservice?

查看:269
本文介绍了我如何使用异步/等待调用web服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写的 web服务 =htt​​p://www.yiiframework.com/doc/指南/ 1.1 / EN / topics.webservice> Yii的(PHP框架)。



我使用C#和Visual Studio 2012开发WP8应用程序。我添加了一个服务引用到我的项目(​​添加服务引用)。所以我能够使用Web服务的功能。



 客户端=新YChatWebService.WebServiceControllerPortTypeClient(); 

client.loginCompleted + = client_loginCompleted; // this.token = e.Result;
client.loginAsync(this.username,this.password);

client.getTestCompleted + = client_getTestCompleted;
client.getTestAsync(this.token);



功能 getTestAsync loginAsync 收益无效无一不是异步的。有可能是功能回到任务< T> ?我想用异步 / 等待在我的程序的关键字。



答:



感谢您的帮助。



继。代码似乎工作

 静态内部类扩展
{
私有静态无效TransferCompletion< T>(
TaskCompletionSource< T> TCS,System.ComponentModel.AsyncCompletedEventArgs E,
Func键< T>的getResult)
{
如果(e.Error = NULL)
{!
tcs.TrySetException(e.Error);
}
,否则如果(e.Cancelled)
{
tcs.TrySetCanceled();
}
,否则
{
tcs.TrySetResult(的getResult());
}
}

公共静态任务< loginCompletedEventArgs> LoginAsyncTask(这YChatWebService.WebServiceControllerPortTypeClient客户端,用户名字符串,字符串密码)
{
变种TCS =新TaskCompletionSource< loginCompletedEventArgs>();
client.loginCompleted + =(S,E)=> TransferCompletion(TCS,电子,()=> E);
client.loginAsync(用户名,密码);
返回tcs.Task;
}
}



我把它叫做这样

 客户端=新YChatWebService.WebServiceControllerPortTypeClient(); 
变种登录=等待client.LoginAsyncTask(this.username,this.password);


解决方案

假设loginAsync返回void,并loginCmpleted事件触发时登录完成后,这就是所谓的基于事件的异步模式,或EAP



要转换EAP等待/异步,咨询的Tasks和基于事件的异步模式。特别是,你要利用TaskCompletionSource到基于事件的模型转换为基于任务的模式。一旦你已经有了一个基于任务的模型,您可以使用C#5的性感等待功能



下面是一个例子:

  //使用LoginCompletedEventArgs,或任何你需要什么了.loginCompleted事件
的//这是一个扩展方法,并且需要被放置在一个静态类。
公共静态任务< LoginCompletedEventArgs> LoginAsyncTask(这YChatWebService.WebServiceControllerPortTypeClient客户端,用户名字符串,字符串密码)
{
VAR TCS = CreateSource< LoginCompletedEventArgs>(NULL);
client.loginCompleted + =(发件人,E)=> TransferCompletion(TCS,电子,()=> E,NULL);
client.loginAsync(用户名,密码);
返回tcs.Task;
}

私有静态TaskCompletionSource< T> CreateSource< T>(对象状态)
{
返回新TaskCompletionSource< T>(
状态,TaskCreationOptions.None);
}

私有静态无效TransferCompletion< T>(
TaskCompletionSource< T> TCS,AsyncCompletedEventArgs E,
Func键< T>的getResult,动作unregisterHandler)
{
如果(e.UserState == TCS)
{
如果(e.Cancelled)tcs.TrySetCanceled();
,否则如果(e.Error!= NULL)tcs.TrySetException(e.Error);
,否则tcs.TrySetResult(的getResult());
如果(unregisterHandler!= NULL)u​​nregisterHandler();
}
}

现在您已转换基于事件的异步编程模型以任务为基础的,现在可以使用等待:

  VAR的客户=新YChatWebService.WebServiceControllerPortTypeClient(); 
变种登录=等待client.LoginAsyncTask(MyUserName输入,MYPASSWORD);


I have a webservice written in Yii (php framework).

I use C# and Visual Studio 2012 to develop a WP8 application. I added a service reference to my project (Add Service Reference). So I am able to use webservice functions.

   client = new YChatWebService.WebServiceControllerPortTypeClient();

   client.loginCompleted += client_loginCompleted;   // this.token = e.Result;
   client.loginAsync(this.username, this.password); 

   client.getTestCompleted += client_getTestCompleted;
   client.getTestAsync(this.token); 

function getTestAsync and loginAsync return void and both are asynchronous. Is it possible for the functions to return Task<T>? I would like to use async/await keywords in my program.

Answer:

Thank you for your help.

Following code seems to work.

    internal static class Extension
    {
        private static void TransferCompletion<T>(
            TaskCompletionSource<T> tcs, System.ComponentModel.AsyncCompletedEventArgs e, 
    Func<T> getResult)
        {
            if (e.Error != null)
            {
                tcs.TrySetException(e.Error);
            }
            else if (e.Cancelled)
            {
                tcs.TrySetCanceled();
            }
            else
            {
                tcs.TrySetResult(getResult());
            }
        }

        public static Task<loginCompletedEventArgs> LoginAsyncTask(this YChatWebService.WebServiceControllerPortTypeClient client, string userName, string password)
        {
            var tcs = new TaskCompletionSource<loginCompletedEventArgs>();
            client.loginCompleted += (s, e) => TransferCompletion(tcs, e, () => e);
            client.loginAsync(userName, password);
            return tcs.Task;
        }
    }

I call it this way

        client = new YChatWebService.WebServiceControllerPortTypeClient();
        var login = await client.LoginAsyncTask(this.username, this.password);

解决方案

Assuming that loginAsync returns void, and loginCmpleted event fires when login is done, this is called the Event-based Asynchronous Pattern, or EAP.

To convert EAP to await/async, consult Tasks and the Event-based Asynchronous Pattern. In particular, you'll want to make use of the TaskCompletionSource to convert the event-based model to a Task-based model. Once you've got a Task-based model, you can use C# 5's sexy await feature.

Here's an example:

// Use LoginCompletedEventArgs, or whatever type you need out of the .loginCompleted event
// This is an extension method, and needs to be placed in a static class.
public static Task<LoginCompletedEventArgs> LoginAsyncTask(this YChatWebService.WebServiceControllerPortTypeClient client, string userName, string password) 
{ 
    var tcs = CreateSource<LoginCompletedEventArgs>(null); 
    client.loginCompleted += (sender, e) => TransferCompletion(tcs, e, () => e, null); 
    client.loginAsync(userName, password);
    return tcs.Task; 
}

private static TaskCompletionSource<T> CreateSource<T>(object state) 
{ 
    return new TaskCompletionSource<T>( 
        state, TaskCreationOptions.None); 
}

private static void TransferCompletion<T>( 
    TaskCompletionSource<T> tcs, AsyncCompletedEventArgs e, 
    Func<T> getResult, Action unregisterHandler) 
{ 
    if (e.UserState == tcs) 
    { 
        if (e.Cancelled) tcs.TrySetCanceled(); 
        else if (e.Error != null) tcs.TrySetException(e.Error); 
        else tcs.TrySetResult(getResult()); 
        if (unregisterHandler != null) unregisterHandler();
    } 
}

Now that you've converted the Event-based async programming model to a Task-based one, you can now use await:

var client = new YChatWebService.WebServiceControllerPortTypeClient();
var login = await client.LoginAsyncTask("myUserName", "myPassword");

这篇关于我如何使用异步/等待调用web服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆