2010-03-17 42 views
2

是否有任何現有管道在BackgroundWorker中批量運行WCF調用?如何在Silverlight中運行批量WCF服務調用BackgroundWorker

很明顯,因爲所有的Silverlight WCF調用都是異步的 - 如果我在後臺工作中運行它們,它們都會立即返回。

我只是不想實施一個討厭的黑客,如果這是一個很好的方式來運行服務調用並收集結果。

  • 不事關什麼樣的順序,他們在
  • 所有操作完成獨立
  • 我想有不超過5項運行一次

編輯:我我也注意到(使用Fiddler時)任何時候都不能發送超過7個電話。即使運行在瀏覽器外,此限制也適用。這是由於我的默認瀏覽器設置 - 還是可配置的。顯然它是一個窮人的解決方案(並不適合我想要的),但我可能需要考慮的事情,以確保我的應用程序的其餘部分保持響應,如果我運行這個作爲背景任務,不要想要使用我所有的連接。

回答

9

我認爲你最好的選擇是讓你的主線程把服務請求項放到一個與BackgroundWorker線程共享的隊列中。然後,BackgroundWorker可以從Queue中讀取數據,並在它檢測到新項目時,啓動異步WCF服務請求,並設置爲處理AsyncCompletion事件。在從不同線程調用Enqueue()或Dequeue()之前,不要忘記鎖定隊列。

下面是一些代碼,提出了一種解決方案的開頭:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 

namespace MyApplication 
{ 
    public class RequestItem 
    { 
     public string RequestItemData { get; set; } 
    } 

    public class ServiceHelper 
    { 
     private BackgroundWorker _Worker = new BackgroundWorker(); 
     private Queue<RequestItem> _Queue = new Queue<RequestItem>(); 
     private List<RequestItem> _ActiveRequests = new List<RequestItem>(); 
     private const int _MaxRequests = 3; 

     public ServiceHelper() 
     { 
      _Worker.DoWork += DoWork; 
      _Worker.RunWorkerAsync(); 
     } 

     private void DoWork(object sender, DoWorkEventArgs e) 
     { 
      while (!_Worker.CancellationPending) 
      { 
       // TBD: Add a N millisecond timer here 
       //  so we are not constantly checking the Queue 

       // Don't bother checking the queue 
       // if we already have MaxRequests in process 
       int _NumRequests = 0; 
       lock (_ActiveRequests) 
       { 
        _NumRequests = _ActiveRequests.Count; 
       } 
       if (_NumRequests >= _MaxRequests) 
        continue; 

       // Check the queue for new request items 
       RequestItem item = null; 
       lock (_Queue) 
       { 
        RequestItem item = _Queue.Dequeue(); 
       } 
       if (item == null) 
        continue; 

       // We found a new request item! 
       lock (_ActiveRequests) 
       { 
        _ActiveRequests.Add(item); 
       } 

       // TBD: Initiate an async service request, 
       //  something like the following: 
       try 
       { 
        MyServiceRequestClient proxy = new MyServiceRequestClient(); 
        proxy.RequestCompleted += OnRequestCompleted; 
        proxy.RequestAsync(item); 
       } 
       catch (Exception ex) 
       { 
       } 
      } 
     } 

     private void OnRequestCompleted(object sender, RequestCompletedEventArgs e) 
     { 
      try 
      { 
       if (e.Error != null || e.Cancelled) 
        return; 

       RequestItem item = e.Result; 

       lock (_ActiveRequests) 
       { 
        _ActiveRequests.Remove(item); 
       } 
      } 
      catch (Exception ex) 
      { 
      } 
     } 

     public void AddRequest(RequestItem item) 
     { 
      lock (_Queue) 
      { 
       _Queue.Enqueue(item); 
      } 
     } 
    } 
} 

讓我知道如果我可以提供更多的幫助。

+0

謝謝吉姆 - 除了你沒有解決的最重要的事情是,我不希望所有的請求一次運行。我認爲毫秒計時器應該檢查ActiveRequests> = 3。我喜歡排隊的想法。其中一個通用類我總是忘記 – 2010-03-22 17:27:15

+0

Simon, 您不必一次運行所有請求。我建議的計時器只是爲了避免持續檢查隊列。 我通過檢查_MaxRequests,並通過包括一個示例調用異步服務,與相應的Completed事件處理程序更新我的答案代碼。希望這會讓你更接近一點。 – 2010-03-22 20:08:23

相關問題