Потоки нескольких асинхронных вызовов - PullRequest
6 голосов
/ 01 мая 2009

Часть моего приложения Silverlight требует данных из трех запросов на обслуживание. До сих пор я составлял цепочку запросов так, что один завершает другой запуск ... до конца цепочки, где я делаю то, что мне нужно делать с данными.

Теперь я знаю, что это не лучший метод (!). Я смотрел на AutoResetEvent (ссылка на пример MSDN) для потоковой передачи, а затем синхронизировал результаты, но, похоже, не могу заставить его работать с асинхронными вызовами службы.

У кого-нибудь есть основания сомневаться в этом методе или он должен работать? Образцы кода с благодарностью получены!

Ответы [ 2 ]

7 голосов
/ 01 мая 2009

Взгляните на этот пример:

Будет запускать событие «Завершено» и печатать «готово» для вывода отладочной информации после возврата обеих служб. Главное, чтобы ожидание AutoResetEvents происходило в фоновом потоке.


public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();

        Completed += (s, a) => { Debug.WriteLine("done"); };

        wrk.DoWork += (s, a) =>
            {
                Start();
            };

        wrk.RunWorkerAsync();
    }
    public event EventHandler Completed;

    private void Start()
    {
        auto1.WaitOne();
        auto2.WaitOne();

        Completed(this, EventArgs.Empty);
    }

    public AutoResetEvent auto1 = new AutoResetEvent(false);
    public AutoResetEvent auto2 = new AutoResetEvent(false);

    BackgroundWorker wrk = new BackgroundWorker();

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        ServiceReference1.Service1Client clien = new SilverlightAsyncTest.ServiceReference1.Service1Client();

        clien.DoWorkCompleted += new EventHandler<SilverlightAsyncTest.ServiceReference1.DoWorkCompletedEventArgs>(clien_DoWorkCompleted);
        clien.DoWork2Completed += new EventHandler<SilverlightAsyncTest.ServiceReference1.DoWork2CompletedEventArgs>(clien_DoWork2Completed);

        clien.DoWorkAsync();
        clien.DoWork2Async();
    }

    void clien_DoWork2Completed(object sender, SilverlightAsyncTest.ServiceReference1.DoWork2CompletedEventArgs e)
    {
        Debug.WriteLine("2");
        auto1.Set();
    }

    void clien_DoWorkCompleted(object sender, SilverlightAsyncTest.ServiceReference1.DoWorkCompletedEventArgs e)
    {
        Debug.WriteLine("1");
        auto2.Set();
    }
}
3 голосов
/ 12 августа 2009

Это можно сделать с помощью WaitHandle в IAsyncResult, возвращаемом каждым асинхронным методом.

Код прост. В Silverlight я просто делаю 10 сервисных вызовов, которые добавят элемент в ListBox. Я подожду, пока все вызовы службы не прекратятся, чтобы добавить еще одно сообщение в список (это должно выполняться в другом потоке, чтобы избежать блокировки пользовательского интерфейса). Также обратите внимание, что добавление элементов в список должно выполняться через диспетчер, так как они изменят пользовательский интерфейс. Есть куча лямд, но за ней легко следить.

 public MainPage()
        {
            InitializeComponent();
            var results = new ObservableCollection<string>();
            var asyncResults = new List<IAsyncResult>();
            resultsList.ItemsSource = results;
            var service = new Service1Client() as Service1;

            1.To(10).Do(i=>
                asyncResults.Add(service.BeginDoWork(ar =>
                    Dispatcher.BeginInvoke(() => results.Add(String.Format("Call {0} finished: {1}", i, service.EndDoWork(ar)))),
                    null))
            );

            new Thread(()=>
            {
                asyncResults.ForEach(a => a.AsyncWaitHandle.WaitOne());
                Dispatcher.BeginInvoke(() => results.Add("Everything finished"));
            }).Start();
        }

Просто чтобы помочь с тестированием, это услуга

public class Service1
    {
        private const int maxMilliSecs = 500;
        private const int minMillisSecs = 100;
        [OperationContract]
        public int DoWork()
        {
            int millisSecsToWait = new Random().Next(maxMilliSecs - minMillisSecs) + minMillisSecs;
            Thread.Sleep(millisSecsToWait);
            return millisSecsToWait;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...