Какой использовать, WebClient.OpenRead, OpenReadAsync или OpenReadTaskAsync - PullRequest
0 голосов
/ 23 ноября 2018

Я пытаюсь понять разницу между WebClient.OpenRead, WebClient.OpenReadAsync и WebClient.OpenReadTaskAsync.

Похоже, у них есть различия в отношении блокировки потока, но я не очень хорошо понимаю.
Не могли бы вы объяснить различия?Было бы здорово, если бы вы могли привести мне пример (примеры не должны быть примерами кода, но было бы здорово, если бы вы могли предоставить)

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

Как вы сказали, разница заключается в поведении блокировки потоков.Первый ( OpenRead () ) - операция блокировки потоков, два других - нет.Например, предположим, что латентность вашей сети для достижения google.com составляет 300 мс.Когда вы делаете var stream = webClient.OpenRead(@"https://www.google.com");, ваше приложение "ставится на паузу" на эти 300 мс, поэтому код рядом с этой строкой не будет выполняться, пока ваш webClient не вернет поток в переменную stream.Это вызывает Блокировка потока .

Когда вы делаете это в UI-потоке (например: в обработчике нажатия кнопки) - ваше приложение зависает и не реагирует на действия пользователя.Это плохо пользовательский опыт, поэтому никогда не вызывайте блокировку потоков в вашем интерфейсе.Вот пример для консольного приложения:

var address = @"https://www.google.com/";

Console.WriteLine($"Opening stream from {address}");
using (var stream = webClient.OpenRead(address)) // this will block for 300ms
{
    Console.WriteLine("Stream is open!");
    // some other code
}

Второй метод ( OpenReadAsync () ) равен асинхронно и не возвращает ничего сразу после вызова, поэтому ваш поток незаблокирован.Через некоторое время (300 мс) webClient будет вызвано событие OpenReadCompleted , и все подключенные слушатели будут обрабатывать открытый поток один за другим.Вот пример:

public partial class MainForm : Form
{
    private WebClient _client = new WebClient();

    public MainForm()
    {
        InitializeComponents();
        _client.OpenReadCompleted += OpenReadCompletedHandler;
    }

    private void ButtonClickHandler(object sender, EventArgs e)
    {
        _client.OpenReadAsync(@"https://www.google.com/");
    }

    private void OpenReadCompletedHandler(object sender, OpenReadCompletedEventArgs e)
    {
        // this event will be raiesed 300ms after 'Button' click
        var stream = e.Result; // <- here is your stream
        // some other code
    }
}

Последний ( OpenReadTaskAsync () ) полностью о TPL (Task Parallel Library) и async / ждут ключевых слов.Он запускает все вещи в Task, который возвращается этим методом.Вот пример:

public partial class MainForm : Form
{
    private WebClient _client = new WebClient();

    public MainForm()
    {
        InitializeComponents();
    }

    private async void ButtonClickHandler(object sender, EventArgs e)
    {
        // after 'await' keyword, execution will be returned from this method immediately
        // meanwhile, actual acquiring of 'stream' is running in a background thread
        using (var stream = await _client.OpenReadTaskAsync(@"https://www.google.com/"))
        {
            // after 300ms, this code will be continued in UI thread
            // result will be automaticly unpacked to 'stream' variable

            // some other code
        }
    }
}

Надеюсь, это поможет.

0 голосов
/ 23 ноября 2018

Я бы предположил, что WebClient более или менее устарел, HttpClient больше подходит для всего, что предназначено для .NET Framework 4.5+ или .NET core.Просто обратите внимание, что последний автоматически не генерирует исключения для кодов ошибок HTTP (400+).

...