2009-05-01 19 views
6

Parte della mia applicazione Silverlight richiede dati da tre richieste di assistenza. Fino ad ora ho incatenato le richieste così come si completano le altre inizia ... fino alla fine della catena in cui faccio ciò che devo fare con i dati.Threading di più chiamate asincrone

Ora, so che non è il metodo migliore (!). Ho cercato AutoResetEvent (collegamento all'esempio MSDN) per eseguire il thread e quindi sincronizzare i risultati, ma non riesco a farlo funzionare con chiamate di servizio asincrone.

Qualcuno ha qualche motivo per dubitare di questo metodo o dovrebbe funzionare? Esempi di codice ricevuti con gratitudine!

risposta

7

Date un'occhiata a questo esempio:

sparerà caso Completato e stampare 'fatto' di output di debug una volta entrambi i servizi restituiti. La cosa fondamentale è che l'attesa di AutoResetEvents avviene nel thread in background.


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(); 
    } 
} 
+0

domanda. hai auto1 per DoWork2. Se hai avuto 3 chiamate asincrone. vuoi semplicemente aggiungere auto3 e impostarlo nell'evento DoWork3Completed? – H20rider

3

Potrebbe essere fatto utilizzando il WaitHandle nel IAsyncResult restituita da ciascun metodo asincrono.

Il codice è semplice. In Silverlight faccio solo 10 chiamate di servizio che aggiungeranno un oggetto a un ListBox. Aspetterò fino a quando tutte le chiamate di servizio terminano per aggiungere un altro messaggio alla lista (questo deve essere eseguito in un thread diverso per evitare di bloccare l'interfaccia utente). Si noti inoltre che l'aggiunta di voci all'elenco deve essere eseguita tramite il Dispatcher poiché modificherà l'interfaccia utente. Ci sono un sacco di lamdas, ma è facile da seguire.

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(); 
     } 

solo per aiutare con i test, questo è il servizio

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; 
     } 
    } 
Problemi correlati