2009-05-01 63 views
6

Một phần của ứng dụng Silverlight của tôi yêu cầu dữ liệu từ ba yêu cầu dịch vụ. Cho đến bây giờ tôi đã chuỗi các yêu cầu để một trong những hoàn thành khác bắt đầu ... cho đến khi kết thúc chuỗi nơi tôi làm những gì tôi cần phải làm gì với dữ liệu.Threading nhiều cuộc gọi không đồng bộ

Bây giờ, tôi biết rằng đó không phải là phương pháp tốt nhất (!). Tôi đã xem xét AutoResetEvent (liên kết đến ví dụ MSDN) đến chuỗi và sau đó đồng bộ hóa kết quả nhưng dường như không thể làm điều này để làm việc với các cuộc gọi dịch vụ không đồng bộ.

Có ai có bất kỳ lý do gì để nghi ngờ phương pháp này hay cách này có hiệu quả không? Các mẫu mã đã được đón nhận nồng nhiệt!

Trả lời

7

Hãy xem ví dụ sau:

sẽ cháy, sự kiện hoàn thành và in 'làm' vào Debug Output một lần cả hai dịch vụ trả lại. Điều quan trọng là chờ đợi AutoResetEvents xảy ra trong chủ đề nền.


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

Câu hỏi. bạn có auto1 cho DoWork2. Nếu bạn có 3 cuộc gọi không đồng bộ. bạn sẽ chỉ thêm auto3 và đặt nó trong sự kiện DoWork3Completed? – H20rider

3

Nó có thể được thực hiện bằng cách sử dụng WaitHandle trong IAsyncResult trả về bởi mỗi phương pháp async.

Mã đơn giản. Trong Silverlight, tôi chỉ thực hiện 10 cuộc gọi dịch vụ để thêm một mục vào ListBox. Tôi sẽ đợi cho đến khi tất cả các cuộc gọi dịch vụ kết thúc để thêm một tin nhắn khác vào danh sách (điều này phải chạy trong một luồng khác để tránh chặn giao diện người dùng). Cũng lưu ý rằng việc thêm các mục vào danh sách phải được thực hiện thông qua Dispatcher vì chúng sẽ sửa đổi giao diện người dùng. Có rất nhiều lamdas, nhưng rất dễ làm theo.

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

Chỉ cần để giúp đỡ với việc thử nghiệm, đây là dịch vụ

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; 
     } 
    } 
Các vấn đề liên quan