30

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.

4

5 に答える 5

35

loginAsync が void を返し、ログインが完了したときに loginCmpleted イベントが発生すると仮定すると、これはイベント ベースの非同期パターン (EAP) と呼ばれます。

EAP を await/async に変換するには、Tasks and the Event-based Asynchronous Pattern を参照してください。特に、TaskCompletionSource を利用して、イベント ベースのモデルをタスク ベースのモデルに変換する必要があります。タスク ベースのモデルを取得したら、C# 5 のセクシーな await 機能を使用できます。

次に例を示します。

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

イベント ベースの非同期プログラミング モデルをタスク ベースの非同期プログラミング モデルに変換したので、await を使用できるようになりました。

var client = new YChatWebService.WebServiceControllerPortTypeClient();
var login = await client.LoginAsyncTask("myUserName", "myPassword");
于 2012-12-31T15:42:20.163 に答える
7

サービス参照を追加するときは、セクションで選択Generate Task based operationsしたことを確認してくださいAdvancedLoginAsyncこれにより、戻るなどの待機可能なメソッドが作成されますTask<string>

于 2012-12-31T15:28:52.630 に答える
-4

メソッドを待機できるようにする場合は、Task を返す必要があります。void を返すメソッドを待機することはできません。int のように値を返すようにしたい場合Task<int>は、メソッドが int を返す必要があります。

public async Task loginAsync(string username, string password) {}

その後、あなたは呼び出すことができます

Task t = loginAsync(username, password);
//login executing
//do something while waiting

await t; //wait for login to complete
于 2012-12-31T15:44:13.943 に答える