Несколько асинхронных вызовов веб-клиентов в фоновом режиме (Silverlight 4) - PullRequest
3 голосов
/ 16 сентября 2011

Требование :

  • Клиент Silverlight, который загружает файл с компьютера пользователя.
  • Для каждой строки в файле необходимо выполнить GET для URL-адреса и утвердить или отклонить строку на основе возвращенного сообщения проверки JSON.
  • Когда все строки завершены, покажите пользователю сводку количества пройденных строк и неудачных.

Я бы предпочел сделать это "синхронно" в BackgroundWorker, ноэто нарушает асинхронное мышление SL.

Мой код в настоящее время передает результат из OpenFileDialog в BackgroundWorker, который считывает файл в список строго типизированных объектов (проверка на стороне клиента).Я создаю WebClient и вызываю DownloadStringAsync несколько раз, пока я зацикливаюсь на строках.Чаще всего фоновый работник завершает и запускает завершенный метод события задолго до завершения работы WebClient.Поток пользовательского интерфейса может работать как асинхронно, как ему хочется, но мне нужно либо дождаться завершения потока фонового работника, пока он фактически не завершит получение данных, либо иметь дополнительный обработчик событий, который работает, когда все (сотни) строк были проверены.

Какова наилучшая практика при обработке последнего завершенного события из общего числа событий X?Любое использование здесь событий автоматического сброса, которые могут помочь?

Ответы [ 2 ]

1 голос
/ 17 сентября 2011

Вы можете выбрать между последовательностью случайного ответа (но параллельное выполнение) или упорядоченным ответом, но в последовательном режиме.Есть разные минусы и плюсы.

using System;
using System.Net;
using System.Reactive.Linq;//Rx libriary
using System.Threading;
using System.Windows;
using System.Windows.Controls;

public partial class MainPage : UserControl
{
    private int count = 0;
    private int error = 0;

    public MainPage()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        ThreadPool.QueueUserWorkItem(StartParallel);
        //ThreadPool.QueueUserWorkItem(StartSequential);
    }

    private void Update(Exception exception)
    {
        if (exception == null)
            Interlocked.Increment(ref count);
        else
            Interlocked.Increment(ref error);
        if ((count%100) == 0)
        {
            int count1 = count;
            Dispatcher.BeginInvoke(() => { textBox.Text = count1.ToString(); });
        }
    }

    private void StartSequential(object o)
    {
        //single instance of  WebClient
        WebClient wc = new WebClient();
        var observer = Observable.FromEventPattern<DownloadStringCompletedEventArgs>(wc, "DownloadStringCompleted")
            .Select(newResult => new {newResult.EventArgs.Error, newResult.EventArgs.Result});

        wc.DownloadStringAsync(new Uri("http://localhost:7123/SilverlightApplication2TestPage.aspx"));
        int i = 0;
        foreach (var nextValue in observer.Next())
        {
            if (i == 10000) break;
            wc.DownloadStringAsync(new Uri("http://localhost:7123/SilverlightApplication2TestPage.aspx"));
            Update(nextValue.Error);
        }
    }

    private void StartParallel(object o)
    {
        for (int i = 0; i < 10000; i++)
        {
            //multiple instance of WebClient
            WebClient t = new WebClient();
            t.DownloadStringCompleted +=
                (x, nextValue) => Update(nextValue.Error);//order of result sequence is not guaranteed
            t.DownloadStringAsync(new Uri("http://localhost:7123/SilverlightApplication2TestPage.aspx"));
        }
    }
}
1 голос
/ 16 сентября 2011

Для этого вам не нужно переходить в фоновый поток, а также не нужно использовать AutoResetEvent здесь. После прочтения файла подсчитайте количество строк (= количество отправленных вами запросов) и сохраните его в переменной экземпляра; затем запустите все WebRequest.DownloadAsync (или какой-либо другой WebClient асинхронный вызов для загрузки данных). При каждом обратном вызове для асинхронного метода вы будете Interlock.Decrement переменную экземпляра, а когда она достигнет 0, вы будете знать, что у вас есть все результаты, и вы можете отобразить сводку для клиента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...