0

Использую async метод, чтобы получить html со страницы, но форма блокируется:

public partial class Test : Form
{
    HttpClient httpClient = new HttpClient();
public async Task<string> GetSource(string url)
{
    using (HttpResponseMessage result = await httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
    {
        result.EnsureSuccessStatusCode();
        return await result.Content.ReadAsStringAsync();
    }
}

private async Task GetSourcePage()
{
    string s = await GetSource("ссылка");
}

private async void StartButtonClick(object sender, EventArgs e)
{
    try
    {
        await GetSourcePage();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

}

В чём может быть проблема?

Aimon Z.
  • 1,045

2 Answers2

2

https://stackoverflow.com/questions/56029988/sendasync-is-blocking-ui-thread

GetAsync использует метод SendAsync

К сожалению, по историческим причинам SendAsync не является чисто асинхронным. В частности, он синхронно выполняет поиск DNS и разрешение прокси. Итак, чтобы сделать это полностью неблокирующим, вам нужно будет обернуть этот вызов в Task.Run

Aimon Z.
  • 1,045
0

Используйте асинхронный вариант обработки события:

async void StartButtonClick(object sender, EventArgs e)
{
    await GetSourcePage();
}
CrazyElf
  • 71,194
  • А как можно вставить туда работу с UI ведь, в асинхронных методах нельзя работать с UI? – Aimon Z. Aug 18 '20 at 14:16
  • @AimonZ. Я не уверен на 100%, но, кажется, можно, если вы уже находитесь в UI потоке. Вот если вы будете пытаться асинхронно работать с UI не из потока UI - тогда да, будут проблемы. Вот здесь подробно всё расписано, если что: https://ru.stackoverflow.com/a/514533/260769 – CrazyElf Aug 18 '20 at 14:29
  • @AimonZ. Конечно можно, но не напрямую, а через Invoke. – Геннадий П Aug 18 '20 at 14:29
  • @ГеннадийП Invoke попросту выглядит некрасиво... И если вы уже в потоке UI (а ButtonClick ведь в потоке UI?), то Invoke не нужен по идее. – CrazyElf Aug 18 '20 at 14:30
  • @CrazyElf Ну, сделать отдельный метод, в который передавать нужные параметры, в котором делать проверку на InvokeRequired от которого и запускать через Invoke либо напрямую. – Геннадий П Aug 18 '20 at 14:36
  • @ГеннадийП Invoke - это что-то из прошлых веков до эпохи async/await ) – CrazyElf Aug 18 '20 at 14:39
  • 1
    не надо никакого Invoke. Если асинхронный метод стартовал из UI потока, то по окончанию метода управление вернется в UI поток. – tym32167 Aug 18 '20 at 14:45
  • Благодаря самой из отвратительных ошибок, сотворенных Microsoft с .NET, раз в 10 лет, когда вы создаёте десктопное приложение, вам не нужно писать .ConfigureAwait(true), так что исполнение после окончания асинхронной задачи возобновится в UI потоке. Плата за это несущественна: всего-то во всех остальных местах нам теперь нужно вечно писать .ConfigureAwait(false), превращая красивый и понятный код в кашу – Kir_Antipov Aug 18 '20 at 15:04
  • 1
    @Kir_Antipov у автора логика на эвентах от UI контролов, там скорее всего уже каша. – tym32167 Aug 18 '20 at 15:13
  • @tym32167, вот и я о чем. Кашу кашей не испортишь. Почему нельзя было сделать как раз возврат в оригинальный поток опциональным? Здесь от .ConfigureAwait(true) хуже уже не станет ¯\(ツ) – Kir_Antipov Aug 18 '20 at 15:16
  • 1
    @Kir_Antipov так это ж значение по умолчанию, толку от него? – tym32167 Aug 18 '20 at 15:17
  • @tym32167, я говорю о том, что это значение по умолчанию - чудовищная ошибка :) Это я тут на Microsoft ропчу и рассуждаю, как могло бы быть хД – Kir_Antipov Aug 18 '20 at 15:19
  • 1
    @Kir_Antipov а, я понял. Ну, не сказал бы, что это прям кричтичная ошибка. Невозможно все предусмотреть, когда выкатывашь такую объемную фичу как async-await. В моих прошлых проектах были такие проблемы, что эта просто казалось несущественной мелочью :) – tym32167 Aug 18 '20 at 15:23
  • @tym32167, предусмотреть все, конечно, нереально. Но ошибка все же критичная: постоянно с матами бегаешь по всей кодовой базе и расставляешь несчастный ConfigureAwait хД Очень надеюсь, что это в конце концов исправят, ибо, как по мне, проблема вполне себе заслуживает стать вторым в истории C# breaking change – Kir_Antipov Aug 18 '20 at 15:36