簡體   English   中英

wcf回調參考

[英]wcf callback reference

我有一個帶有雙工WCF服務的桌面應用程序,但是使用回調存在一些麻煩。

該服務在program.cs的主要部分中按以下方式啟動:

ServiceHost svcHost = new ServiceHost(typeof(PeriodicService));
svcHost.Open();
Console.WriteLine("Available Endpoints :\n");
svcHost.Description.Endpoints.ToList().ForEach(endpoint =>   Console.WriteLine(endpoint.Address.ToString() + " -- " + endpoint.Name));

對於該服務,我創建了一個訂閱函數,其中回調通道保存在全局變量中,然后回調使用該全局變量與客戶端進行通訊(只有一個客戶端在連接)。

IPeriodicCallback callbackClient;

public IPeriodicCallback Proxy
{
     get
     {
        return this.callbackClient;
     }
}

public void joinPeriodicService()
{
    Console.WriteLine("Client subscribe");
    this.callbackClient = OperationContext.Current.GetCallbackChannel<IPeriodicCallback>();
}

我現在想做的是從另一個類中調用callbackclient。 在另一個類中,我將服務創建為:

private PeriodicService periodicService = new PeriodicService();

我嘗試使用以下方法向其中寫入數據:

if(this.periodicService.Proxy != null)
{ 
     this.periodicService.Proxy.On1MinuteDataAvailable(tmpPeriod);
}

但是,代理保持為空,我也嘗試將代理部分移至類,但這也導致其保持為空。

當客戶端連接時,我很好地收到消息“客戶端訂閱”,但似乎有兩個實例正在運行periodicservice。

但是我的問題是我沒有看到其他訪問周期服務的方法,然后在我的類中創建它,或者它是否已經由svcHost創建?

誰能指出我正確的方向?

該存儲庫顯示了我之前回答類似問題的雙工WCF實現,它是一個完整的工作示例,並盡可能減少了額外的工作量。

https://github.com/Aelphaeis/MyWcfDuplexPipeExample

可以說我們有這樣的服務合同:

[ServiceContract(CallbackContract = typeof(IMyServiceCallback),SessionMode = SessionMode.Required)]
public interface IMyService
{
    [OperationContract(IsOneWay=true)]
    void DoWork();
}

請注意,我指定了一個CallbackContract。 如果要進行雙工,則可能希望使上述合同的服務行為實現如下:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyService : IMyService
{
    public void DoWork()
    {
        Console.WriteLine("Hello World");
        Callback.WorkComplete();
    }

    IMyServiceCallback Callback
    {
        get
        {
            return OperationContext.Current.GetCallbackChannel<IMyServiceCallback>();
        }
    }
}

這里重要的是回調。 這就是您的服務將允許您訪問客戶端指定給您的方式。

您還需要定義回調接口,就我而言,它非常簡單:

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

現在,我想創建一個客戶端來使用此雙工服務。 我需要做的第一件事是實現IMyServiceCallback。 我需要在客戶端上執行此操作。 在這種情況下,實現是這樣的:

class Callback : IMyServiceCallback
{
    public void WorkComplete()
    {
        Console.WriteLine("Work Complete");
    }
}

現在,當我想打開與服務的雙工連接時,我將創建一個像這樣的代理類:

public class MyServiceClient: IMyService, IDisposable
{
    DuplexChannelFactory<IMyService> myServiceFactory { get; set; }

    public MyServiceClient(IMyServiceCallback Callback)
    {
        InstanceContext site = new InstanceContext(Callback);
        NetNamedPipeBinding binding = new NetNamedPipeBinding();
        EndpointAddress endpointAddress = new EndpointAddress(Constants.myPipeService + @"/" + Constants.myPipeServiceName);

        myServiceFactory = new DuplexChannelFactory<IMyService>(site, binding, endpointAddress);
    }

    public void DoWork()
    {
        myServiceFactory.CreateChannel().DoWork();
    }

    public void Dispose()
    {
        myServiceFactory.Close();
    }
}

注意,我指定了InstanceContext。 該實例上下文將是我創建的實現IMyServiceCallback的對象的實例。

這就是您需要做的! 就那么簡單!

更新 :回調對象與其他任何對象一樣。 您可以將它們存儲到一個集合中,並根據某種條件遍歷它們。

一種方法是在IMyServiceCallback中創建可以唯一標識它的屬性。 當客戶端連接到服務時,它可以調用一個方法,該方法指定一個回調對象,然后可以將其緩存或保存以供以后使用。 然后,您可以迭代回調,並根據某些條件可以為特定客戶端調用方法。

這當然更加復雜。 但是,它肯定是可管理的。 我將添加一個示例。

更新2這是您想要的實際示例。 但是,它要復雜得多。 我將嘗試盡可能簡單地進行解釋: https : //github.com/Aelphaeis/MyWcfDuplexPipeExample/tree/MultiClient

以下是更改列表:

  • 我已經修改了客戶端代理(和服務),以便在初始化時調用init方法。
  • 我還修改了Service實現,以便現在它是處理所有請求的單個實例(為方便起見)。
  • 我在服務接口中添加了一個名為Msg的新OperationContract
  • 我在IMyServiceCallback中添加了一個名為RecieveMessage的新方法。
  • 我添加了一種識別客戶端的方法。

在代理類中,我有以下內容:

public MyServiceClient(IMyServiceCallback Callback)
{
    InstanceContext site = new InstanceContext(Callback);
    NetNamedPipeBinding binding = new NetNamedPipeBinding();
    EndpointAddress endpointAddress = new EndpointAddress(Constants.myPipeService + @"/" + Constants.myPipeServiceName);
    myServiceFactory = new DuplexChannelFactory<IMyService>(site, binding, endpointAddress);
    Init();
}
public void Init()
{
    myServiceFactory.CreateChannel().Init();
}

為我服務:

public class MyService : IMyService
{
    public List<IMyServiceCallback> Callbacks { get; private set; }

    public MyService(){
        Callbacks = new List<IMyServiceCallback>();
    }

    public void Init()
    {
        Callbacks.Add(Callback);
    }
// and so on

我的IMyServiceCallback已重新定義為:

[ServiceContract]
public interface IMyServiceCallback 
{
    [OperationContract]
    int GetClientId();

    [OperationContract(IsOneWay = true)]
    void WorkComplete();

    [OperationContract(IsOneWay = true)]
    void RecieveMessage(String msg);
}

通過指定一個號碼,您可以聯系與該號碼相對應的客戶。 如果兩個客戶具有相同的ID,則將聯系這兩個客戶。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM