0

我有以下情况: 我的 WCF 服务允许客户端注册以等待某个事件。等待在服务端是异步的,即注册服务员,当进程完成后,通知服务员。目前,它只是一个ManualResetEvent.

现在我想通过 WCF 公开这个方法。我尝试使用AsyncPattern=true并创建了两种方法,BeginWait它们将事件捆绑到 中IAsyncResult,并EndWait调用AsyncWaitHandle.WaitOne(). 但是,如果我从客户端调用BeginWait,则不会执行服务器端。我正在使用手动实现的包装器(我的代理类是从 派生的),它基本上调用,并且确实调用了这个函数;但在服务器端,电话永远不会到达。EndWaitEndWaitChannelBase<IWaitService>, IWaitServiceChannel.EndWait()

我在这里做错了什么?后续问题:如果异步调用正常工作,是否有一种简单的方法可以在客户端实现同步?

4

2 回答 2

2

线

var task = Task.Factory.StartNew(() => IsPrime(a));  

使用重载

TaskFactory.StartNew(Action)

这导致

((IAsyncResult)task).AsyncState == null

对 callback(task) 的调用导致 ArgumentException,抱怨状态对象与传递给 BeginXxx 方法的状态对象不同。该行必须修改为

var task = Task.Factory.StartNew((actionState) => IsPrime(a), state);  

使用重载

TaskFactory.StartNew(Action<object>, object)

这样 WCF 传递的状态对象最终会出现在任务中:

((IAsyncResult)task).AsyncState.GetType().FullName == System.ServiceModel.Dispatcher.MessageRpc+Wrapper
于 2011-07-29T16:11:23.440 回答
0

同步/异步决策可以在服务器端或客户端独立做出。在客户端调用 EndWait 不会转换为在服务器上调用 EndWait。我建议使用同步客户端测试异步服务,以保持简单并避免混淆。

我进一步建议您不要在 EndWait 方法中调用 WaitOne。约定是只有在 IAsyncResult 告诉框架它完成后才会调用此方法。这是通过以下三种方式之一完成的:

  • CompletedSynchronously 返回 true
  • 调用 AsyncCallback
  • 向 AsyncWaitHandle 发出信号

CompletedSynchronously 应该仅在 BeginWait 在返回之前有足够的信息来完成请求的情况下返回 true。情况可能并非如此。您可以使用 ManualResetEvent 满足其他两个条件,如下所示:

class EventBasedAsyncResult : IAsyncResult
{
    private readonly ManualResetEvent _manualResetEvent;
    private readonly AsyncCallback _asyncCallback;
    private readonly object _asyncState;

    public EventBasedAsyncResult(AsyncCallback callback, object asyncState)
    {
        _manualResetEvent = new ManualResetEvent(false);
        _asyncState = asyncState;
        _asyncCallback = callback;
    }

    public void WaitCompleted()
    {
        _manualResetEvent.Set();
        _asyncCallback(this);
    }

    public object AsyncState
    {
        get { return _asyncState; }
    }

    public WaitHandle AsyncWaitHandle
    {
        get { return _manualResetEvent; }
    }

    public bool CompletedSynchronously
    {
        get { return false; }
    }

    public bool IsCompleted
    {
        get { return _manualResetEvent.WaitOne(0); }
    }
}

我想一旦你这样做,你会发现 EndWait 被调用,即使客户端是同步的。

于 2011-05-23T19:52:50.667 回答