2009-05-01 21 views
6

मेरे सिल्वरलाइट एप्लिकेशन का हिस्सा तीन सेवा अनुरोधों से डेटा की आवश्यकता है। अब तक मैं अनुरोधों को चेन कर रहा हूं ताकि एक दूसरे की शुरुआत पूरी कर सके ... श्रृंखला के अंत तक जहां मैं डेटा के साथ क्या करना चाहता हूं।एकाधिक एसिंक कॉल थ्रेडिंग

अब, मुझे पता है कि यह सबसे अच्छी विधि नहीं है (!)। मैं AutoResetEvent (एमएसडीएन उदाहरण से लिंक) को थ्रेड पर देख रहा हूं और फिर परिणामों को सिंक्रनाइज़ कर रहा हूं लेकिन यह एसिंक सेवा कॉल के साथ काम करने के लिए प्रतीत नहीं होता है।

क्या किसी के पास इस विधि पर संदेह करने का कोई कारण है या यह काम करना चाहिए? संहिता नमूने आभारी रूप से प्राप्त!

उत्तर

7

इस उदाहरण पर एक नज़र डालें:

पूरे घटना और डिबग आउटपुट के लिए प्रिंट 'पूर्ण' एक बार दोनों सेवाओं लौटे सक्रिय हो जाएगा। मुख्य बात यह है कि स्वत: रीसेट की प्रतीक्षा पृष्ठभूमि थ्रेड में होती है।


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

प्रश्न है। आपके पास DoWork2 के लिए auto1 है। अगर आपके पास 3 एसिंक कॉल थे। क्या आप केवल ऑटो 3 जोड़ देंगे और इसे DoWork3 पूर्ण ईवेंट में सेट करेंगे? – H20rider

3

यह WaitHandle का उपयोग किया जा सकता है IAsyncResult में प्रत्येक async विधि से लौट आए।

कोड सरल है। सिल्वरलाइट में मैं केवल 10 सेवा कॉल करता हूं जो एक सूची को सूची बॉक्स में जोड़ देगा। मैं तब तक प्रतीक्षा करूंगा जब तक कि सभी सेवा कॉल सूची में कोई अन्य संदेश जोड़ने के लिए समाप्त न हों (यूआई को अवरुद्ध करने से बचने के लिए इसे एक अलग थ्रेड में चलाना होगा)। यह भी ध्यान रखें कि सूची में आइटम को डिस्पैचर के माध्यम से करना होगा क्योंकि वे यूआई को संशोधित करेंगे। लैमडास का एक गुच्छा है, लेकिन इसका पालन करना आसान है।

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; 
     } 
    } 
संबंधित मुद्दे