Я понимаю, что этому вопросу уже почти год, но если ограничения спрашивающего остаются, в .NET 3.5 есть опция, позволяющая легко составлять асинхронные операции.Посмотрите на библиотеку PowerThreading Джеффа Рихтера .В пространстве имен Wintellect.PowerThreading.AsyncProgModel
вы найдете несколько вариантов класса AsyncEnumerator
, которые вы можете использовать с генераторами последовательностей для написания асинхронного кода, как если бы он был последовательным.
Суть в том, что вы пишетеваш асинхронный код является телом генератора последовательности, который возвращает IEnumerator<int>
, и всякий раз, когда вы вызываете асинхронный метод, вы запускаете yield return
с количеством ожидающих асинхронных операций.Библиотека обрабатывает кровавые подробности.
Например, чтобы опубликовать некоторые данные в URL и вернуть содержимое результата:
public IAsyncResult BeginPostData(string url, string content, AsyncCallback callback, object state)
{
var ae = new AsyncEnumerator<string>();
return ae.BeginExecute(PostData(ae, url, content), callback, state);
}
public string EndPostData(IAsyncResult result)
{
var ae = AsyncEnumerator<string>.FromAsyncResult(result);
return ae.EndExecute(result);
}
private IEnumerator<int> PostData(AsyncEnumerator<string> ae, string url, string content)
{
var req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.BeginGetRequestStream(ae.End(), null);
yield return 1;
using (var requestStream = req.EndGetRequestStream(ae.DequeAsyncResult()))
{
var bytes = Encoding.UTF8.GetBytes(content);
requestStream.BeginWrite(bytes, 0, bytes.Length, ae.end(), null);
yield return 1;
requestStream.EndWrite(ae.DequeueAsyncResult());
}
req.BeginGetResponse(ae.End(), null);
yield return 1;
using (var response = req.EndGetResponse(ae.DequeueAsyncResult()))
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream))
{
ae.Result = reader.ReadToEnd();
}
}
Как видите, приватный PostData()
Метод отвечает за основную часть работы.Существует три запущенных асинхронных метода, о чем свидетельствуют три оператора yield return 1
.С помощью этого шаблона вы можете связать столько асинхронных методов, сколько захотите, и при этом просто вернуть один IAsyncResult
вызывающей стороне.