2013-10-18 62 views
1

我想構建一個WCF服務,它接受請求記錄並返回這些記錄的字符串響應。我正在接受一系列請求記錄。在這個數組中,一些記錄被快速處理(「快速記錄」),而另一些則需要時間(「慢速記錄」)。因此,不是等待所有記錄被處理,而是可以先返回快速記錄,然後再發送慢速記錄?客戶端會立即更新屏幕上的快速記錄,並在慢速記錄通過時進行更新。如何構建批量返回數據的WCF服務

我怎樣才能做到這一點與WCF服務?

+0

兩種方法:'GetFastRecords'&'GetSlowRecords' –

+0

也許雙工服務,如果客戶端在.NET實現以及。或者輪詢,方法立即返回「快速記錄」和客戶端間隔調用的另一種方法,直到它具有所有「慢速記錄」。 – trydis

回答

0

如果你可以有雙工支持,我會通過回調。

[ServiceContract] 
public interface IMyServiceCallback 
{   
    [OperationContract(IsOneWay = true)]   
    void OnRecordResult(string result); 
} 

[ServiceContract(CallbackContract = typeof(IMyServiceCallback))] 
public interface IMyService 
{ 
    [OperationContract(IsOneWay = true)] 
    void GetRecords(string parameter); 
} 

public class MyService: IMyService 
{ 
    public void GetRecords(string parameter) 
    { 
     var callback = OperationContext.Current.GetCallbackChannel<IMyServiceCallback>(); 

     using(var resultCollection = ProcessRecords(parameter)) 
     { 
      foreach(var record in resultCollection.GetConsumingEnumerable()) 
      { 
       //Transmit the results back to the client as they get put in to resultCollection. 
       callback.OnRecordResult(record); 
      } 
     } 

     //We return null as a signal that we are done reporting results, you could also add a 2nd method to the callback to represent being done. 
     callback.RecordResult(null); 
    } 

    private static BlockingCollection<string> ProcessRecords(string parameter) 
    { 
     var collection = new BlockingCollection<string>(); 

     //We populate the blocking collection in a background thread. 
     Task.Run(() => StartProcessingRecords(parameter, collection); 

     return collection; 
    } 

    private static void StartProcessingRecords(string parameter, BlockingCollection<string> collection) 
    { 
     //... 
    } 
} 

這裏是你如何在客戶端使用它

public class MyServiceClient : DuplexClientBase<IMyService> 
{ 
    public MyServiceClient(object callbackInstance, Binding binding, EndpointAddress remoteAddress) 
     : base(callbackInstance, binding, remoteAddress) { } 
} 

public class MyServiceCallbackClient : IMyServiceCallback 
{ 
    public event EventHandler<string> RecordResult; //If you are not using .net 4.5 you will need a custom class. 

    void IMyServiceCallback.OnRecordResult(string result) 
    { 
     var tmp = RecordResult; 
     if(tmp != null) 
      tmp(this, result); 
    } 
} 

IEnumerable<string> GetRecords(string parameter) 
{ 
    var uri = //... 
    var binding = //... 

    using(var collection = new BlockingCollection<string>()) 
    { 
     var callback = new MyCallbackClient(); 
     callback.RecordResult += (o, result) => 
     { 
      if(result != null) 
       collection.Add(result); 
      else 
       collection.CompleteAdding(); //when we get a null we mark the collection complete 
     } 


     var client = new MyServiceClient(callback, binding, new EndpointAddress(uri)); 
     var proxy = client.ChannelFactory.CreateChannel(); 
     proxy.GetRecords(); 

     foreach(var record in collection.GetConsumingEnumerable()) 
     { 
      yield return record; 
     } 

     client.Close(); 
    } 
}