2013 Edit: 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);
}
Хотя это, безусловно, работает, это не очень эффективно, поскольку поток делегата будет тратить большую часть своего времени на ожидание двух операций ввода-вывода.
Я хотел бы позвонить request.BeginGetResponse()
, сопоставить регулярное выражение, а затем позвонить imageRequest.BeginGetResponse()
. Все при использовании стандартного шаблона асинхронных вызовов и сохранении подписей BeginGetDilbert () и EndGetDilbert () .
Я пробовал несколько подходов и не был полностью удовлетворен ни одним из них; это похоже на королевскую боль. Отсюда и вопрос. : -)
РЕДАКТИРОВАТЬ: Кажется, что подходы, использующие итераторы, одобрены командой компилятора C # .
Заявление от команды компилятора:
Хотя, несомненно, дело в том, что
Вы можете использовать итераторы для реализации
государственные машины, сопрограммы бедняков,
и так далее, я хотел бы, чтобы люди не делали
так.
Пожалуйста, используйте инструменты для целей
которые они были предназначены. Если ты хочешь
писать конечные автоматы, писать
сами библиотека, которая разработана
специально для решения этого общего
проблема, а затем использовать его.
Использование инструментов для других целей, кроме
для чего они предназначены
«умный», а умный - это плохо; умный
трудно для обслуживания программистов
понимаешь, умное сложно расширить,
умный трудно рассуждать, умный
заставляет людей думать «из коробки»;
в этой коробке есть хорошие вещи.
Переходя к ответу Future<>
, потому что он остается в C #, что совпадает с моим примером кода. К сожалению, ни TPL, ни F # официально не поддерживаются Microsoft ... пока.