私は次のような方法を持っておりTask<string> GetContentAsync(string url)
、私のコンソール アプリケーションは内部で TPL を利用する準備ができていませんが、後日になる可能性があります。
この (または他の) メソッドの同期ラッパー (代替実装ではない) を簡単に作成するにはどうすればよいですか?
私は次のような方法を持っておりTask<string> GetContentAsync(string url)
、私のコンソール アプリケーションは内部で TPL を利用する準備ができていませんが、後日になる可能性があります。
この (または他の) メソッドの同期ラッパー (代替実装ではない) を簡単に作成するにはどうすればよいですか?
ライブラリに同期メンバーと非同期メンバーの両方を実装する必要がある場合は、両方のメンバーを実装します。ショートカットはありません (これが再利用可能なライブラリであることを前提としています)。
public async Task<string> GetContentAsync(string url)
{
... // Logic here, e.g., using HttpClient
}
public string GetContent(string url)
{
... // Duplicate logic here, e.g., using WebClient
}
ロジックの重複は確かに残念ですが、ショートカットしようとすると、実際にはさらに悪い状況に陥ります。「理由」の詳細は、SO の回答としては少し長くなりますが、Stephen Toub は、彼の古典的なブログ投稿「非同期メソッドの同期ラッパーを公開する必要がありますか?」でラップするときに発生する問題について説明しています。および「同期メソッドの非同期ラッパーを公開する必要がありますか?」
ところで、両方の質問に対する答えは「いいえ」です。また、SOの回答はこちらをご覧ください。
これを非常に簡単な方法で実行できることを示すテスト ケースのコードを次に示します。GetContentAsync
デモンストレーション用のメソッドも実装しました。
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace AsyncTestCase.Driver
{
public class AsyncTestCase
{
public AsyncTestCase()
{ }
public string GetContent(string url)
{
Task<string> task = this.GetContentAsync(url);
return task.Result;
}
public async Task<string> GetContentAsync(string url)
{
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse;
using (Stream stream = response.GetResponseStream())
{
using (TextReader reader = new StreamReader(stream))
{
string content = await reader.ReadToEndAsync();
return content;
}
}
}
}
}
これが問題なく動作し、操作が簡単であることを示すコードを次に示します。
namespace AsyncTestCase.Driver
{
internal static class Program
{
private static void Main()
{
AsyncTestCase test = new AsyncTestCase();
string content = test.GetContent("http://www.google.com");
}
}
}