【发布时间】:2009-03-19 01:41:02
【问题描述】:
2013 年编辑: async 和 await 现在让这变得微不足道! :-)
我有一些屏幕抓取网站的代码(仅用于说明目的!)
public System.Drawing.Image GetDilbert()
{
var dilbertUrl = new Uri(@"http://dilbert.com");
var request = WebRequest.CreateDefault(dilbertUrl);
string html;
using (var webResponse = request.GetResponse())
using (var receiveStream = webResponse.GetResponseStream())
using (var readStream = new StreamReader(receiveStream, Encoding.UTF8))
html = readStream.ReadToEnd();
var regex = new Regex(@"dyn/str_strip/[0-9/]+/[0-9]*\.strip\.gif");
var match = regex.Match(html);
if (!match.Success) return null;
string s = match.Value;
var groups = match.Groups;
if (groups.Count > 0)
s = groups[groups.Count - 1].ToString(); // the last group is the one we care about
var imageUrl = new Uri(dilbertUrl, s);
var imageRequest = WebRequest.CreateDefault(imageUrl);
using (var imageResponse = imageRequest.GetResponse())
using (var imageStream = imageResponse.GetResponseStream())
{
System.Drawing.Image image_ = System.Drawing.Image.FromStream(imageStream, true /*useEmbeddedColorManagement*/, true /*validateImageData*/);
return (System.Drawing.Image)image_.Clone(); // "You must keep the stream open for the lifetime of the Image."
}
}
现在,我想异步调用 GetDilbert()。使用委托的简单方法:
Func<System.Drawing.Image> getDilbert;
IAsyncResult BeginGetDilbert(AsyncCallback callback, object state)
{
getDilbert = GetDilbert;
return getDilbert.BeginInvoke(callback, state);
}
System.Drawing.Image EndGetDilbert(IAsyncResult result)
{
return getDilbert.EndInvoke(result);
}
虽然这确实有效,但效率并不高,因为委托线程将花费大部分时间等待两个 I/O 操作。
我想做的是调用request.BeginGetResponse(),进行正则表达式匹配,然后调用imageRequest.BeginGetResponse()。同时使用标准异步调用模式并保留 BeginGetDilbert() 和 EndGetDilbert() 的签名。
我尝试了几种方法,但都没有完全满意;这似乎是一种皇家的痛苦。因此,问题。 :-)
编辑:似乎使用迭代器的方法是frowned on by the C# compiler team。
编译器团队的请求:
虽然可以肯定的是 你可以使用迭代器来实现 状态机,穷人协程, 等等,我希望人们不要这样做 所以。
请使用用于以下目的的工具 这是他们的本意。如果你想 写状态机,写 自己设计的图书馆 专门解决那个一般 问题,然后使用它。
将工具用于其他目的 他们的目的是 “聪明”,聪明是坏的;聪明的是 维护程序员很难 明白,聪明难以扩展, 聪明很难推理,聪明 让人们思考“开箱即用”; 那个盒子里有好东西。
使用 Future<> 答案,因为它保留在 C# 中,这与我的示例代码相同。不幸的是,TPL 和 F# 都没有得到 Microsoft 的正式支持……目前。
【问题讨论】:
-
你能提供这个
2013 Edit: async and await now make this trivial! :-)的例子吗?我为此添加了 +1!
标签: c# .net multithreading asynchronous iasyncresult