2017-03-01 94 views
5

Şu anda bir uygulamayı bir wcf istemcisi üzerinden yönetmek zorunda olduğum bir proje üzerinde çalışıyorum. Karşılaştığım sorun, sunucuya bir çağrı yaptıktan sonra müşterinin geri aranması için beklemesini istemesidir. Şu senaryo:wcf istemcisini geri arama için bekleyin

Bir pencereyi gösteren ve daha sonra sunucu uygulaması boş olan servise çağrı yapıyorum. Pencerede bir düğmeyi tıkladığımda, istemciye bir geri dönüş yapar. Bu süre boyunca istemci kullanıcı arabirimi devre dışı bırakılmalıdır - geri arama için beklemek zorundadır. Bana bunu nasıl başarabileceğimi söyler misiniz? Concurrency Mode veya Operation Contract niteliği ile bir ilgisi var mı?

Bu ServiceContract ve CallbackContract benim kodudur:

[ServiceContract(CallbackContract = typeof(IWCFServiceCallback))] 
public interface IWCFService 
{ 
    [OperationContract] 
    void OpenWindow(); 
} 
public interface IWCFServiceCallback 
{ 
    [OperationContract(IsOneWay = true)] 
    void ReturnValue(object[] value); 
} 

cevap

0

Teşekkür yapılandırılmış olduğunda geri aramasında kilidini gerekir. Win32 ShowWindow işlevini kullanarak sorunu çözdüm.

1

Hayır, tarif özellik eşzamanlılık Mode veya Operasyonu Sözleşme ile ilgisi yoktur. Semaforları (Mutex, Monitor, ne olursa olsun ...) kullanarak ve semaforu ayarlamak için sunucudan istemciye geri aramaları yapmanız gerekir.

Açıkladığınız işlevsellik gerçekten tuhaf görünüyor.

1

Bunu, bir zaman uyumsuz hizmet işlemi uygulayarak ve Async/Await kullanarak arayarak yapabilirsiniz.

İstemcinizi, hizmetinizi çağırmadan hemen önce devre dışı bırakın ve sonra geri arama geri döndükten sonra etkinleştirin.

https://msdn.microsoft.com/en-us/library/ms731177.aspx

using System; 
using System.Collections.Generic; 
using System.ServiceModel; 
using System.Text; 
using System.Threading; 

namespace Microsoft.WCF.Documentation 
{ 
    [ServiceContractAttribute(Namespace="http://microsoft.wcf.documentation")] 
    public interface ISampleService{ 

    [OperationContractAttribute] 
    string SampleMethod(string msg); 

    [OperationContractAttribute(AsyncPattern = true)] 
    IAsyncResult BeginSampleMethod(string msg, AsyncCallback callback, object asyncState); 

    //Note: There is no OperationContractAttribute for the end method. 
    string EndSampleMethod(IAsyncResult result); 

    [OperationContractAttribute(AsyncPattern=true)] 
    IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState); 

    // Note: There is no OperationContractAttribute for the end method. 
    string EndServiceAsyncMethod(IAsyncResult result); 
    } 

    public class SampleService : ISampleService 
    { 
    #region ISampleService Members 

    public string SampleMethod(string msg) 
    { 
     Console.WriteLine("Called synchronous sample method with \"{0}\"", msg); 
     return "The sychronous service greets you: " + msg; 
    } 

    // This asynchronously implemented operation is never called because 
    // there is a synchronous version of the same method. 
    public IAsyncResult BeginSampleMethod(string msg, AsyncCallback callback, object asyncState) 
    { 
     Console.WriteLine("BeginSampleMethod called with: " + msg); 
     return new CompletedAsyncResult<string>(msg); 
    } 

    public string EndSampleMethod(IAsyncResult r) 
    { 
     CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>; 
     Console.WriteLine("EndSampleMethod called with: " + result.Data); 
     return result.Data; 
    } 

    public IAsyncResult BeginServiceAsyncMethod(string msg, AsyncCallback callback, object asyncState) 
    { 
     Console.WriteLine("BeginServiceAsyncMethod called with: \"{0}\"", msg); 
     return new CompletedAsyncResult<string>(msg); 
    } 

    public string EndServiceAsyncMethod(IAsyncResult r) 
    { 
     CompletedAsyncResult<string> result = r as CompletedAsyncResult<string>; 
     Console.WriteLine("EndServiceAsyncMethod called with: \"{0}\"", result.Data); 
     return result.Data; 
    } 
    #endregion 
    } 

    // Simple async result implementation. 
    class CompletedAsyncResult<T> : IAsyncResult 
    { 
    T data; 

    public CompletedAsyncResult(T data) 
    { this.data = data; } 

    public T Data 
    { get { return data; } } 

    #region IAsyncResult Members 
    public object AsyncState 
    { get { return (object)data; } } 

    public WaitHandle AsyncWaitHandle 
    { get { throw new Exception("The method or operation is not implemented."); } } 

    public bool CompletedSynchronously 
    { get { return true; } } 

    public bool IsCompleted 
    { get { return true; } } 
    #endregion 
    } 
} 
+0

Cevabınız için teşekkür ederiz. Yöntemi çağırdıktan sonra, istemcinin, yöntemin kendisi (geri arama olmadan) değeri döndürüyormuş gibi davranmasını istiyorum. Müşteri, hizmetin çalışmasını tamamlayıp, bir değer döndürdüğünü bekler. Kullanıcı arayüzünü manuel olarak kilitleyemem çünkü istemci, Excel'i devre dışı bırakabileceğim hiçbir form/pencere içermeyen bir eklentidir. – Bartek

+0

Excel'de bir FunctionWizard açıkken servis çağrısı yapılır, bu yüzden hücreleri kilitleyemiyorum çünkü Excel çöküyor. – Bartek

+0

@Bartek - Bu, ayrı bir Soru-Cevap için farklı bir sorun. Bu sorunun cevabını verdiğime inanıyorum, ama eğer bana haber vermezseniz ve daha fazla yardımcı olmaya çalışacağım. FYI, Microsoft'un kendi örnek kodunda kendi [önerilen adlandırma kurallarını] ortadan kaldırdığını belirtiyor (https://msdn.microsoft.com/en-us/library/mt674882.aspx#Anchor_7). Eşzamansız işlevler, adlarına "Async" eklenmiş olmalıdır. Burada "async" anahtar kelimesini görmüyoruz, ancak bu yine de asenkron bir mimaridir. – InteXX

1

concurrenymode ConcurrencyMode.Single ve müşteri hizmeti çağrıları, hizmet kilit yaratacaktır. IsOneWay ile geri arama arabirimini çağırdığında yanlış bir sonuç mesajı hizmete geri gönderilir. Servis kilidi tekrar oluşturacak ve kilit hala müşteri çağrısından tutulduğu için kilitlenecektir. ConsurrencyMode ile . Reentrant, geri çağırırken geri getirildiğinde kilitlenecek ve böylece bunu kullanabilmeniz için kilitlenecektir. IsOneWay = true, aynı zamanda hizmetin geri çağrılmasına neden sonuç mesajı gönderilmediğinden de bir çözümdür.

Yani sadece servisi çağırmadan önce size GUI kilitlemek mümkün ve geri arama operasyonu IsOneWay = true varsa veya servis ConcurrencyMode.Reentrant cevaplar için

+0

Sorun, bir FunctionWizard açık olan bir Excel AddIn olduğu gibi, istemcinin UI'sini el ile kilitleyemem. Hücreleri kilitlemeye çalışırsam, Excel çöküyor. – Bartek