Асинхронный WebClient не совсем асинхронный?


Я создал асинхронный WebClient запрос внутри класса следующим образом:

public class Downstream
    {
        public bool StartDownstream()
        {
            WebClient client = new WebClient();

            client.Headers.Add("user-agent", "Mozilla/4.0 [...]");
            client.Headers.Add("Content-Type","application/x-www-form-urlencoded");
            try
            {

                byte[] postArray = Encoding.UTF8.GetBytes("somevar=foo&someothervar=bar");
                Uri uri = new Uri("http://www.examplesite.com/somepage.php");

                client.UploadDataCompleted += 
                new UploadDataCompletedEventHandler(client_UploadDataCompleted);
                client.UploadDataAsync(uri, postArray);
            }
            catch (WebException e)
            {
                MessageBox.Show("A regular Web Exception");
            }
            catch (NotSupportedException ne)
            {
                MessageBox.Show("A super Web Exception");
            }
            return true;
        }

        void client_UploadDataCompleted(object sender, UploadDataCompletedEventArgs e)
        {
            MessageBox.Show("The WebClient request completed");
        }
    }

Затем я создаю новый экземпляр класса и запускаю метод здесь:

Downstream Downstream1 = new Downstream();
Downstream1.StartDownstream();

Когда я делаю это, поток, на котором выполняется форма, кажется, зависает, пока WebClient не получит ответ обратно. Почему это так? Я использовал метод UploadDataAsync, поэтому он не должен быть асинхронным?

Правка:

Это мой стек вызовов:

    [External Code] 
>   Arcturus.exe!Arcturus.Downstream.StartDownstream() Line 36 + 0x18 bytes C#
    Arcturus.exe!Arcturus.MainWindow.btnLogin_Click(object sender, System.Windows.RoutedEventArgs e) Line 111 + 0x12 bytes  C#
    [External Code]

Это все, что происходит, когда я запускаю свое приложение, просто висит на методах StartDownstream() и client.UploadDataAsync(uri, postArray);.

3 5

3 ответа:

Моя проблема заключалась в том, что WebClient использовал тот же поток, что и пользовательский интерфейс, независимо от того, асинхронный он или нет. Вместо этого я решил использовать BackgroundWorker.

Спасибо за ответы!

Просто предположим, имеет ли ваша основная форма атрибут STAThread, установленный на ней? Если ваше приложение не имеет никаких вызовов COM, то вы можетебезопасно удалить этот атрибут . Возможно, он может заставить UploadDataAsync работать в том же потоке, что и основная форма, блокируя ее.

Во-первых, вы должны использовать ключевое слово await перед клиентом.UploadDataAsync (uri, postArray). Поэтому следует "дождаться клиента".UploadDataAsync (uri, postArray); "

Во-вторых, поскольку вы используете ключевое слово await в своем методе, вам нужно написать асинхронное начало объявления метода и задачи вместо bool. Поэтому это должна быть асинхронная публичная задача StartDownstream () {..}

После этих двух шагов, поскольку ваш метод StardDownstream асинхронен, вы также должны ожидать его. Используйте его, как ждать Downstream1.StartDownstream ();

Если у меня есть какая-либо ошибка, дайте мне знать, потому что я новичок в этой теме.