1

我正在寻找一种方法让客户端调用从客户端 UI 到 WCF 服务主机的异步进程,然后通知客户端进程的状态。我想这可以通过 sagas(流程管理器)、域事件和 WCF 双工连接来实现,但我不确定如何!

案例顺序(我猜)如下:

  1. 客户端调用进程
  2. 客户端创建 WCF 代理
  3. 代理连接到服务主机
  4. 服务主机创建到客户端的双工通道
  5. 服务主机使用命令总线启动进程并通过双工通道
  6. 进程状态改变!
  7. 定位相关双工通道
  8. 推回状态更改
  9. 客户接收状态变化并可视化

我说得对吗?简而言之,相关的类会是什么样子?是的,我知道 NServiceBus(在这种情况下经常被提及),但我不想依赖额外的框架(我已经有很多 NServiceBus 可以自己解决的问题,而且我已经在使用数百个各种东西的不同框架..)

编辑: 示例 这里有一个可能指定我的问题的真实示例。

我有一个图像处理服务器,它可以用图像做一些神奇和独角兽的东西。WCF 客户端将图像上传到服务器,然后显示一个进度条,指示已处理了多少图像。服务器启动一个新的 ImageProcessService(在请求范围内)。在处理过程中,他可能会抛出大量 ImageProcessStateChanged 事件,其中的数字以百分比表示进程。完成后,他可能会抛出一个 ImDoneEvent。所有事件都应该被事件总线捕获,事件总线将它们发回给正确的客户端。该过程最多可能需要 60 秒,并且可以为每个客户端触发一次,但针对尽可能多的客户端。

4

2 回答 2

4

听起来您正在寻找的只是通过在操作合同上设置 IsOneWay=true 启用的行为。当您在操作合约中设置 IsOneWay=true 时,调用方会发送请求但不会等待响应。为了得到您的响应,被调用者需要在您的双工通道的回调通道上调用另一个操作,该通道也设置了 IsOneWay=true。

这是一个简单的示例:

服务合约:

[ServiceContract( CallbackContract = typeof( IClientCallback ), SessionMode = SessionMode.Required )]
public interface IClientService
{
    [OperationContract( IsInitiating = true )]
    void CreateSession( string windowsUserName );
    [OperationContract( IsOneWay = true )]
    void LongOp( );
    [OperationContract( IsTerminating = true )]
    void Terminate( );
}

客户端回调合约:

[ServiceContract]
public interface IClientCallback
{
    [OperationContract( IsOneWay = true )]
    void LongOpResponse( );
}

服务实施:

class ServerService : IClientService
{
    public void CreateSession( string windowsUserName )
    {
        //Do stuff to set up your session as desired
    }

    public void LongOp( )
    {
        //Do something that takes a long time
        LongRunningFunctionCall();
        Callback.LongOpResponse();
    }

    public void Terminate( )
    {
        //Do stuff to tear down your session
    }

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

客户端回调实现:

class CallbackHandler : IClientCallback
{
    public void LongOpResponse( )
    {
        Console.WriteLine( "Received long operation response from server." );
    }
}

只要您拥有对处理每个会话的客户端服务对象的引用,您就可以直接通过该对象访问其回调通道,因此您可以从服务器应用程序中的任何点启动回调合约上的函数,只要通道是开放的。

我们通常会在双工通道的服务合同中完成比 IsOneWay=false 更多的单向操作,除了立即响应对调用应用程序的继续至关重要的操作。

于 2014-06-05T18:06:47.943 回答
0

这可以使用 Task Parallelism 或 IAsyncResult 来实现。

IAsyncResult 在其 AsyncWaitHandle 上有一个 WaitOne,因此客户端可以等待它完成异步执行,然后通过调用异步方法的 End 调用来获取值。

例子是。

public IAsyncResult Process(type param, AsyncCallback callback, object state)
{
   // code here to process
}

public TypeResult EndProcess(IAsyncResult ar)
{
   // return result here
}

现在回调可用于从您的客户端调用方法,在您的情况下,可用于通知状态。

关于 IAsyncResult 的详细信息:这里

于 2014-06-02T06:35:21.160 回答