0

もちろんSilverlightを使用するWindowsPhoneアプリケーションで忙しいです。つまり、Webサービスの呼び出しは非同期で行う必要があります。これは、リソースを待機しているときにアプリ全体がハングしないようにするためのベストプラクティスに関してはすべて適切であり、「同期の考え方」にとらわれています。 ..

私が今見ているのは、1つの関数を処理する必要がある2つのメソッドがあるということです。

1)実際にWebサービスを呼び出すメソッド:

public void myAsyncWebService(DownloadStringCompletedEventHandler callback)
{
    //Url to webservice
    string servletUrl = "https://deangrobler.com/someService/etc/etc"

    //Calls Servlet
    WebClient client = new WebClient();
    client.DownloadStringCompleted += callback;
    client.DownloadStringAsync(new Uri(servletUrl, UriKind.Absolute));
}

2)そしてデータが最終的に戻ってきたときにデータを処理するメソッド:

private void serviceReturn(object sender, DownloadStringCompletedEventArgs e)
{
    var jsonResponse = e.Result;
    //and so on and so forth...
}

したがって、Webサービスにアクセスする単一のメソッドを作成して呼び出す代わりに、返された結果を取得して、次のように私に送り返します。

public string mySyncWebService(){
    //Calls the webservice
    // ...waits for return
    //And returns result
}

クラスでmyAsyncWebServiceを呼び出し、myAsyncWebService によって返される結果を処理する別のメソッドを呼び出し元のクラスに作成する必要があります。ただ、私の意見では、厄介なコードを作成します。同期呼び出しを使用すると、1つのメソッドを呼び出すだけで、それを実行できます。

非同期呼び出しを間違って使用しているだけですか?私の理解は間違っていますか?私はここでいくつかの啓蒙が必要です、私はこの厄介な非同期呼び出しをするのが嫌いです。それは私のコードを複雑にしすぎて、読みやすさはただ...地獄に行きます。

私の心を変えてくれる人に感謝します!

4

5 に答える 5

2

非同期でプログラミングするには、心を裏返しにする必要があります。私は経験から話します。:)

非同期呼び出しを間違って使用しているだけですか? 私の理解は間違っていますか?

いいえ。非同期コードは書くのがかなり難しく (エラー処理を忘れないでください)、維持するのが非常に困難です。

asyncこれがとawaitが発明された理由です。

VS2012 にアップグレードできる場合は、Microsoft.Bcl.Async (現在はベータ版) を使用して、次のようにコードを記述できます。

string url1 = "https://deangrobler.com/someService/etc/etc";
string jsonResponse1 = await new WebClient().DownloadStringTaskAsync(url1);

string url2 = GetUriFromJson(jsonResponse1);
string jsonResponse2 = await new WebClient().DownloadStringTaskAsync(url2);

書きやすい。メンテナンスが簡単。

于 2012-11-21T13:28:35.560 に答える
1

代わりにラムダを使用すると、すべてがはるかに簡単で読みやすくなります。これにより、次の例のように、「親」メソッドで宣言された変数にアクセスすることもできます。

private void CallWebService()
{
    //Defined outside the callback
    var someFlag = true;

    var client = new WebClient();
    client.DownloadStringCompleted += (s, e) =>
    {
        //Using lambdas, we can access variables defined outside the callback
        if (someFlag)
        {
            //Do stuff with the result. 
        }
    };

    client.DownloadStringAsync(new Uri("http://www.microsoft.com/"));
}


編集:これは、2つの連鎖サービス呼び出しを使用した別の例です。それはまだあまりきれいではありませんが、私見では、OPの元のコードよりも少し読みやすくなっています。

private void CallTwoWebServices()
{
    var client = new WebClient();
    client.DownloadStringCompleted += (s, e) =>
    {
        //1st call completed. Now make 2nd call.
        var client2 = new WebClient();
        client2.DownloadStringCompleted += (s2, e2) =>
        {
            //Both calls completed.
        };
        client2.DownloadStringAsync(new Uri("http://www.google.com/"));
    };
    client.DownloadStringAsync(new Uri("http://www.microsoft.com/"));
}
于 2012-11-21T11:26:45.680 に答える
1

同期呼び出しを使用すると、1 つのメソッドを呼び出すだけで完了できます。

もちろんですが、UI スレッドからそれを行うと、UI 全体がブロックされます。これは、最新のアプリケーション、特にブラウザーや電話で実行される Silverlight アプリケーションでは受け入れられません。DNS ルックアップがタイムアウトしている間に 30 秒間応答しない電話は、誰も使いたくないものです。

したがって、UI スレッドでは、おそらくユーザーが UI で何らかのアクションを行ったため、非同期呼び出しを開始します。呼び出しが完了すると、バックグラウンド スレッドでメソッドが呼び出され、呼び出しの結果が処理されます。このメソッドは、ほとんどの場合、非同期呼び出しの結果で UI を更新します。

.NET 4.5 での async と await の導入により、この「分割」コードの一部を簡素化できます。幸いなことに、Windows Phone 7.5 では、NuGet パッケージMicrosoft.Bcl.Asyncを使用したベータ版で async と await を利用できるようになりました。

以下は、非同期を使用して 2 つの Web サービス呼び出しを連鎖させる方法を示す小さな (そしてややばかげた) 例です。これは .NET 4.5 で動作しますが、上記のリンクの NuGet パッケージを使用すると、Windows Phone 7.5 でも同様のことができるはずです。

async Task<String> GetCurrencyCode() {
  using (var webClient = new WebClient()) {
    var xml = await webClient.DownloadStringTaskAsync("http://freegeoip.net/xml/");
    var xElement = XElement.Parse(xml);
    var countryName = (String) xElement.Element("CountryName");
    return await GetCurrencyCodeForCountry(countryName);
  }
}

async Task<String> GetCurrencyCodeForCountry(String countryName) {
  using (var webClient = new WebClient()) {
    var outerXml = await webClient.DownloadStringTaskAsync("http://www.webservicex.net/country.asmx/GetCurrencyByCountry?CountryName=" + countryName);
    var outerXElement = XElement.Parse(outerXml);
    var innerXml = (String) outerXElement;
    var innerXElement = XElement.Parse(innerXml);
    var currencyCode = (String) innerXElement.Element("Table").Element("CurrencyCode");
    return currencyCode;
  }
}

ただし、UI スレッドと async の間をブリッジする必要がありますGetCurrencyCode。イベント ハンドラーで待機することはできませんがTask.ContinueWith、非同期呼び出しによって返されたタスクで使用できます。

void OnUserAction() {
  GetCurrencyCode().ContinueWith(GetCurrencyCodeCallback);
}

void GetCurrencyCodeCallback(Task<String> task) {
  if (!task.IsFaulted)
    Console.WriteLine(task.Result);
  else
    Console.WriteLine(task.Exception);
}
于 2012-11-21T11:22:06.017 に答える
1

非同期は、電話をかけたときに留守番電話に応答するときのようなものです。折り返しの電話が必要な場合は、自分の番号を残します。最初のメソッドはデータを要求する呼び出しで、2 つ目はリターン コール用に残した「番号」です。

于 2012-11-21T11:21:18.017 に答える