Можно ли ожидать операции ввода-вывода, которая не объявлена ​​как асинхронная? Если нет, что мне делать?

Я новичок в асинхронном программировании на 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?

Спасибо!

Ответы на вопрос(3)

Ваш ответ на вопрос