2009-12-11 35 views
6

Şu anda bir istemci ve sunucu tarafına ayırma üzerinde çalışıyorum bir WPF uygulamasına sahibim - WCF kullanarak. Başlangıçta düz ileri çözümle karşılaştığım karışıklıktan hoşlanmadım, şimdi Miguel Castro, WCF Extreme belgesindeki tavsiyeleri izleyerek yeniden yapıyorum. Videoya aşina değilseniz, temel olarak tüm iletişimi manuel olarak ayarlar - servis referanslarını kullanmadan. Bunlar:Bir async WCF hizmetinin uygulanması

  • tüm servis ve veri sözleşmeleri ile ortak Sözleşme - istemci ve sunucu tarafından başvurulan
  • hizmet
  • Vekil istemci haritalama hizmeti üzerinde sınıflar ve geçen çağrılar barındıran bir konsol uygulaması bunun için (ClientBase veya ClientFactory kullanarak)

Tüm adımlarını takip ettim ve bunun nereye gittiğini gerçekten çok seviyorum. Ancak, zaman uyumsuz servis çağrılarını ele almıyor ve kullanmak istediğim şey bu.

Bir Hizmet Başvurusu eklerken, "Eşzamansız işlemler üret" onay kutusunu işaretleyebilir ve MyServiceCompleted ve MyServiceAsync'i alırım. Bununla birlikte, bu, hizmet referansı eklendiğinde ortaya çıkan bir şey ve sanırım bu sınıflarda bazı sihir değil mi?

Bu nedenle, bir şekilde ClientBase veya ClientFactory'dan eşzamansız işlemler alabilir miyim? Yoksa asıl sunucu as hizmetlerini async olarak tanımlamalı mıyım? Öyleyse - birisi bana basit bir async hizmetiyle nasıl başlayacağınıza dair birkaç ipucu veya örnek verebilir mi? Konuyla ilgili MSDN üzerinde okumaya başladım, ama bu zaten bunu elde etmek için bir salak gibi tüm kafası karışmış hissetti ..

cevap

5

Sunucu tarafında async işlemleri uygulamak oldukça basittir. Yöntem adlarının eşleştiğinden ve Başlangıç ​​ve Bitiş ile öneklendiğinizden emin olun. GetImageAsyncResult özel bir IAsyncResult uygulamasıdır (web üzerinde çok sayıda örnek).

public class MapProvider : IMapProvider //implementation - belongs to server 
    { 
     public IAsyncResult BeginGetImage(int level, int x, int y, string[] layers, AsyncCallback callback, object state) 
     { 
       GetImageAsyncResult asyncResult = new GetImageAsyncResult(level, x, y, layers, callback, state); 
       ThreadPool.QueueUserWorkItem(Callback, asyncResult); 
       return asyncResult; 
     } 

     private void Callback(object state) 
     { 

       GetImageAsyncResult asyncResult = state as GetImageAsyncResult; 
       asyncResult.Image = TileProvider.GetImage(asyncResult.Level, asyncResult.X, asyncResult.Y, asyncResult.Layers); 
       asyncResult.Complete(); 
     } 

     public System.Drawing.Bitmap EndGetImage(IAsyncResult result) 
     { 
       using (GetImageAsyncResult asyncResult = result as GetImageAsyncResult) 
       { 
        asyncResult.AsyncWait.WaitOne(); 
        return asyncResult.Image; 
       } 
     } 
    } 

    public class MapProviderProxy : ClientBase<IMapProvider>, IMapProvider, IDisposable 
    { 
     public IAsyncResult BeginGetImage(int level, int x, int y, string[] layers, AsyncCallback callback, object state) 
     { 
       return Channel.BeginGetImage(level, x, y, layers, callback, state); 
     } 

     public System.Drawing.Bitmap EndGetImage(IAsyncResult result) 
     { 
       return Channel.EndGetImage(result); 
     } 

     public void Dispose() 
     { 
       if (State == CommunicationState.Faulted) 
       { 
        Abort(); 
       } 
       else 
       { 
        try 
        { 
         Close(); 
        } 
        catch 
        { 
         Abort(); 
        } 
       } 
     } 
    } 
+0

Teşekkürler! "[OperationContract (true AsyncPattern =)]" ile etiketlenmiş - Ve IMapProvider tanımlanan BeginGetImage ve EndGetImage fonksiyonlarına sahip olacaktır? Ve bu özel sonucu GetImageAsyncResult? – stiank81

+0

Doğru - Web'de bir temel AsyncResult sınıfı buldum. GetImageAsyncResult bundan türemiştir. – Goran

+0

Tamam - bu benim sorumu cevaplıyor. Ancak, ben hizmet uyumsuz yapmak istemediğini fark ettik, ama uyumsuz senkron servisini aramak istiyorum. Yani Müşteri tarafında halledeceğim. Bunu AsyncMethodCaller kullanarak kolayca çözerim. Yine de teşekkürler! – stiank81

3

"Async işlemleri oluştur" u seçtiğinizde, İlgili sihirbaz: Begin... iletişiminizi başlatır, sunucu işlemeye başlar, ancak End... numaralı telefonu arayana kadar hiçbir şeyi kullanamazsınız.

Tüm bu davranış, istemci tarafında gerçekleşir, bu nedenle hizmet uygulamanızdaki herhangi bir şeyi değiştirmeniz gerekmez.

Muhtemelen bu karmaşık olmalı düşünüyorsunuz ama öyle görünmüyor;)

DÜZENLEME: Ayrıca açıkça uyumsuz çalışması için hizmet programlamak yapabilirsiniz

using (Service.SampleClient client = new Service.SampleClient()) 
{ 
    client.AddCompleted += 
     (object sender, Service.AddCompletedEventArgs e) 
      { 
       Console.WriteLine(e.Result); // 2 
      }; 
    client.AddAsync(1, 1); 

    // wait for async callback 
    Console.ReadLine(); 
} 

[ServiceContract] 
public interface ISample 
{ 
    [OperationContract] 
    int Add(int a, int b); 
} 

: İşte bir örnek gitmek Burada açıklandığı gibi: Synchronous and Asynchronous Operations, [OperationContract(AsyncPattern=true)]

+0

Ehr .. Lütfen detaylandırır mısınız? Servisleri el değmeden bırakabileceğimi ve müşteri tarafında asenkron işlemeyi uygulayabileceğimi mi söylüyorsun? Evet - Ben üzgünüm – stiank81

+0

ok var yavaş olmak, ama yine de Service.SampleClient nedir? AddCompleted ve AddAsync işlevlerini nereden aldı? –

+0

Teşekkür tutun bir örnek üzerinde çalışıyorum, ben daha karmaşık olarak bu görüyorum yüksek riskli o zaman :-P – stiank81

3

Svcutil kullanmadan istemci tarafında uyumsuz operasyonları gerçekleştirmek için alternatif bir yol uyumsuz işlem uygulayan istemci tarafında yerel bir arayüz (ServiceContract) ayarlamaktır.sunucu tarafında

Sözleşme:

[ServiceContract] 
public interface IServerContract 
{ 
    [OperationContract] 
    string GetData(int value); 
} 
adı ve varsayılan ad eşleşmesi için istemci sözleşme ayarlanmış gerektiğini istemci tarafında

[ServiceContract(Namespace = "http://tempuri.org/", Name = "IServerContract")] 
public interface IClientContractAsync 
{ 
     [OperationContract] 
     Task<string> GetDataAsync(int value); 
} 

Not üzerinde

Async sözleşme Sunucu sözleşmesinin ad alanı. Yani şimdi bir asenkron işleminiz var (umarız yeni bir iş parçacığı başlatmadan). Bu şekilde sunucu tarafında belirli bir uygulama yapmak zorunda değilsiniz. Elbette bu SvcUtil'in yaptıklarına benzer fakat SvcUtil fazladan kod üretir ve bazen svcutil'e problemler çıkarır. sınıfların yeniden kullanılması ile.

ClientProxy

public class ClientProxy : ClientBase<IClientContractAsync> 
{ 
    public IClientContractAsync ChannelOut 
    { 
     get 
     { 
      return Channel; 
     } 
    } 
} 

müşterinin kullanımı:

static void Main(string[] args) 
{ 
    var client = new ClientProxy(); 
    client.Open(); 
    var asyncReadValue = client.ChannelOut.GetDataAsync(45).Result; 
    Console.WriteLine(asyncReadValue); 
    Console.ReadLine(); 
} 

sunucu sınıfı

public class ServerService : IServerContract 
{ 
    public string GetData(int value) 
    { 
     return string.Format("You entered: {0}", value); 
    } 
} 

sunucusu ana

static void Main(string[] args) 
{ 
    var server = new ServiceHost(typeof(ServerService)); 
    server.Open(); 
    Console.WriteLine("started"); 
    Console.ReadLine(); 
} 
İlgili konular