使用wsDualHttpBinding调用WCF

时间:2013-01-26 12:39:04

标签: asp.net wcf signalr

我有一个独立的应用程序,它使用WCF和wsDualHttpBinding。 此独立应用程序将使用wsDualHttpBinding的回调行为随机向任何已订阅服务的客户端发送消息。

如果我们将窗口应用程序用作客户端,则应用程序子目录和回调行为将成功运行。

然后我想创建一个ASP.Net应用程序,它使用SignalR作为服务器推送并描述上述独立应用程序提供的服务。当任何消息从应用程序返回时,我们将使用SignalR来推送消息并在浏览器中显示它。

但是,当试图创建这样的ASP.Net应用程序时,每当从独立应用程序回调消息时,ASP.Net应用程序都将被关闭。

以下是SignalR

的中心代码
 public class MessageSubcriberHub : Hub
{
    private static readonly Dictionary<string, MessageSubcriber> Subcribers = new Dictionary<string, MessageSubcriber>();

    public bool Subcribe()
    {
        if (Subcribers.Keys.Contains(Context.ConnectionId))
        {
            return true;
        }
        try
        {
            MessageSubcriber sub = new MessageSubcriber();
            sub.ConnectionId = Context.ConnectionId;
            if (sub.Subcribe())
            {
                sub.listener += (string message, DateTime time) =>
                {
                    try
                    {
                        var context = GlobalHost.ConnectionManager.GetHubContext<MessageSubcriberHub>();
                        context.Clients.Client(sub.ConntectionId).MessageReceived(message, time);
                    }
                    catch
                    {
                        if (Subcribers.Keys.Contains(sub.ConntectionId))
                        {
                            Subcribers.Remove(sub.ConntectionId);
                        }
                    }
                };
                Subcribers.Add(Context.ConnectionId, sub);
                return true;
            }
            else
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public bool Unsubcribe()
    {
        if (Subcribers.Keys.Contains(Context.ConnectionId))
        {
            try
            {
                Subcribers[Context.ConnectionId].Dispose();
                Subcribers.Remove(Context.ConnectionId);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        return true;
    }

    public override Task OnDisconnected()
    {
        //return Clients.All.leave(Context.ConnectionId, DateTime.Now.ToString());
        return new Task(new Action(()=>{
            if (Subcribers.Keys.Contains(Context.ConnectionId))
            {
                try
                {
                    Subcribers[Context.ConnectionId].Dispose();
                    Subcribers.Remove(Context.ConnectionId);
                }
                catch (Exception ex)
                {
                }
            }
        }));            
    }

以下是回调客户端的代码

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class MessageSubcriber : IMessagingServiceCallback, IDisposable
{
    public string ConnectionId;

    MessagingServiceClient client;
    public delegate void MessageReceivedListener(string message, DateTime time);

    public event MessageReceivedListener listener;

    public MessageSubcriber()
    {
        InstanceContext context = new InstanceContext(this);
        client = new MessagingServiceClient(context, "WSDualHttpBinding_IMessagingService");
    }

    public bool Subcribe()
    {
        return client.Subscribe();
    }

    public bool Unsubcribe()
    {
        return client.Unsubscribe();
    }

    public virtual void MessageReceived(string message, DateTime time)
    {
        if (listener != null)
        {
            listener.Invoke(message, time);
        }
    }

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

我在ASP.net应用程序关闭后检查了事件查看器。以下是事件查看器中显示的消息

  

发生了未处理的异常,并且该过程已终止。

     

申请ID:6ccca6be

     

流程ID:6184

     

异常:System.Runtime.FatalException

     

消息:对象引用未设置为对象的实例。

     

StackTrace:at   System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&安培;   rpc)at   System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc&安培;   rpc)at   System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc&安培;   rpc)at   System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc&安培;   rpc)at   System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&安培;   rpc)at   System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&安培;   rpc)at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean   isOperationContextSet)at   System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(的RequestContext   request,Boolean cleanThread,OperationContext   currentOperationContext)at   System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(的RequestContext   请求,OperationContext currentOperationContext)at   System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult的   结果)在   System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult的   结果)在   System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult的   System.Runtime.AsyncResult.Complete(Boolean。)   完成同步)   System.Runtime.InputQueue 1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue 1.Dispatch()at   System.ServiceModel.Channels.ReliableDuplexSessionChannel.ProcessDuplexMessage(WsrmMessageInfo   信息)   System.ServiceModel.Channels.ClientReliableDuplexSessionChannel.ProcessMessage(WsrmMessageInfo   信息)   System.ServiceModel.Channels.ReliableDuplexSessionChannel.HandleReceiveComplete(IAsyncResult的   结果)在   System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnReceiveCompletedStatic(IAsyncResult的   结果)在   System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult的   System.Runtime.AsyncResult.Complete(Boolean。)   完成同步)   System.Runtime.AsyncResult.Complete(Boolean completedSynchronously,   异常例外)   System.ServiceModel.Channels.ReliableChannelBinder 1.InputAsyncResult 1.OnInputComplete(IAsyncResult的   结果)在   System.ServiceModel.Channels.ReliableChannelBinder 1.InputAsyncResult 1.OnInputCompleteStatic(IAsyncResult的   结果)在   System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult的   System.Runtime.AsyncResult.Complete(Boolean。)   完成同步)   System.Runtime.InputQueue 1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue 1.EnqueueAndDispatch(Item item,Boolean   canDispatchOnThisThread)at   System.Runtime.InputQueue 1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread) at System.ServiceModel.Security.SecuritySessionClientSettings 1.ClientSecurityDuplexSessionChannel.CompleteReceive(IAsyncResult的   结果)在   System.ServiceModel.Security.SecuritySessionClientSettings 1.ClientSecurityDuplexSessionChannel.OnReceive(IAsyncResult result) at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously, Exception exception) at System.ServiceModel.Security.SecuritySessionClientSettings 1.ClientSecuritySessionChannel.ReceiveAsyncResult.OnReceive(IAsyncResult的   结果)在   System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult的   System.Runtime.AsyncResult.Complete(Boolean。)   完成同步)   System.Runtime.AsyncResult.Complete(Boolean completedSynchronously,   异常例外)   System.ServiceModel.Channels.ReliableChannelBinder 1.InputAsyncResult 1.OnInputComplete(IAsyncResult的   结果)在   System.ServiceModel.Channels.ReliableChannelBinder 1.InputAsyncResult 1.OnInputCompleteStatic(IAsyncResult的   结果)在   System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult的   System.Runtime.AsyncResult.Complete(Boolean。)   完成同步)   System.Runtime.InputQueue 1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue 1.Dispatch()at   System.Runtime.InputQueue`1.OnDispatchCallback(Object state)at   System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32的   errorCode,UInt32 numBytes,NativeOverlapped * nativeOverlapped)at   System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32的   错误,UInt32 bytesRead,NativeOverlapped * nativeOverlapped)at   System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32的   errorCode,UInt32 numBytes,NativeOverlapped * pOVERLAP)

     

InnerException:System.NullReferenceException

     

消息:对象引用未设置为对象的实例。

     

StackTrace:at   System.Web.HttpApplication.ThreadContext.Enter(布尔   setImpersonationContext)at   System.Web.HttpApplication.OnThreadEnterPrivate(布尔   setImpersonationContext)at   System.Web.AspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback   回调,对象状态)at   System.Web.AspNetSynchronizationContext.CallCallback(SendOrPostCallback   回调,对象状态)at   System.Web.AspNetSynchronizationContext.Post(SendOrPostCallback   回调,对象状态)at   System.ServiceModel.Dispatcher.ThreadBehavior.BindCore(MessageRpc&安培;   rpc,Boolean startOperation)at   System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&安培;   RPC)

有没有人有任何想法?

1 个答案:

答案 0 :(得分:0)

您的Windows客户端可以在wsDualHttpBinding上运行,因为WCF能够在客户端和WCF服务之间创建持久的会话,该服务在给定的超时时间内持续存在。

ASP.NET是一个服务器端框架,它从指定的应用程序池中抓取一个线程来处理传入的HTTP请求,创建一个HTTP响应并将该线程返回给应用程序池。您遇到的问题是,ASP.NET会拆除任何wsDualHttpBinding创建的会话(这是 NOT 等同于ASP.NET会话)从ASP.NET代码调用时的服务。基本上,ASP.NET应用程序实例化一个WCF客户端,该客户端仅在HTTP请求/响应对的持续时间内保持不变,并且由于拆除过程而删除了您的回调目标

要完成您所描述的内容,您需要在ASP.NET上下文中实现独立的wsDualHttpBinding连接管理器。我认为完全避免使用wsDualHttpBinding绑定并创建一个简单的基于令牌的轮询消息模式来模拟回调机制会更简单。