我有一个方法,例如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");
}
}
}