Можно ли ожидать операции ввода-вывода, которая не объявлена как асинхронная? Если нет, что мне делать?
Я новичок в асинхронном программировании на C #, и я все еще запутался в нескольких вещах. Я читал, что после .NET 4.5 APM и EAP больше не рекомендуются для новых разработок, поскольку TAP должен заменить их (источник).
Я думаю, что понял, как работает async / await, и я смогу использовать их для выполнения операций ввода-вывода, которые имеют асинхронные методы. Например, я мог бы написать асинхронный метод, который ожидает результата GetStringAsync HttpWebClient, так как он объявлен как асинхронный метод. Замечательно.
Мой вопрос: что если у нас есть операция ввода-вывода, которая происходит в методе, который не объявлен как асинхронный? Вот так: предположим, у меня есть API, который имеет метод
string GetResultFromWeb()
который запрашивает что-то из Интернета. И у меня есть много разных запросов, и ядолжен используйте этот метод, чтобы сделать это. И тогда мне нужно обработать каждый результат запроса. Я понимаю, что сделал бы это, если бы это был асинхронный метод:
Task<string> getResultTask = GetResultFromWeb(myUrl);
// Do whatever I need to do that doesn't need the query result
string result = await getResultTask;
Process(result);
Но так как это не так, я не могу ждать этого - это говорит мне, что строка не является ожидаемой. Итак, мой вопрос: есть ли способ выполнить эти операции ввода-вывода асинхронно без необходимости создания одного потока для каждого запроса? Если бы я мог, я бы хотел создать как можно меньше потоков без необходимости блокировать какие-либо потоки.
Один из способов, который я нашел, это реализовать APM, выполнивЭта статья от Джеффри Рихтера, а затем в моем методе Begin я вызываю ThreadPool.QueueWorkItem (GetResultFromWeb, asyncResult). Как это:
public class A {
private void DoQuery(Object ar){
AsyncResult<string> asyncResult = (AsyncResult<string>) ar;
string result = GetResultFromWeb();
asyncResult.SetAsCompleted(result, false);
}
public IAsyncResult BeginQuery(AsyncCallback){
AsyncResult<string> asyncResult = new AsyncResult<string>(callback, this);
ThreadPool.QueueUserWorkItem(DoQuery, asyncResult);
return asyncResult;
}
public string EndQuery(IAsyncResult ar){
AsyncResult<string> asyncResult = (AsyncResult<string>)ar;
return asyncResult.EndInvoke();
}
}
Затем я использую AsyncEnumerator и начинаю (BeginQuery) несколько запросов и обрабатываю результаты по завершении каждого из них (используя yield return / EndQuery). Кажется, это хорошо работает. Но после прочтения настолько, что APM устарел, мне было интересно, как я могу сделать это с помощью TAP. Кроме того, есть ли проблемы с этим подходом APM?
Спасибо!