1

我有一个独立的应用程序,它使用带有 wsDualHttpBinding 的 WCF。这个独立的应用程序将通过使用 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 应用程序关闭后检查了事件查看器。以下是事件查看器中显示的消息

发生未处理的异常,进程终止。

应用编号:6ccca6be

进程 ID:6184

异常:System.Runtime.FatalException

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

StackTrace:在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) 在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) 在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) 在 System.ServiceModel.Dispatcher .ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) 在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) 在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) 在 System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)在 System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext 请求,布尔型 cleanThread,OperationContext currentOperationContext) 在 System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result) 在 System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result) 在 System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext) 在 System .Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult 结果) 在 System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) 在 System.Runtime.InputQueueDispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result) at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) 在 System.Runtime.InputQueueDispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result) at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) 在 System.Runtime.InputQueue1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue1.Dispatch() 在 System.ServiceModel.Channels.ReliableDuplexSessionChannel.ProcessDuplexMessage(WsrmMessageInfo info) 在 System.ServiceModel.Channels.ClientReliableDuplexSessionChannel.ProcessMessage(WsrmMessageInfo info) 在 System.ServiceModel.Channels.ReliableDuplexSessionChannel.HandleReceiveComplete(IAsyncResult 结果) 在系统。 ServiceModel.Channels.ReliableDuplexSessionChannel.OnReceiveCompletedStatic(IAsyncResult 结果) 在 System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult 结果) 在 System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) 在 System.Runtime.AsyncResult.Complete(Boolean completedSynchronously, 异常异常)在 System.ServiceModel.Channels.ReliableChannelBinder1.InputAsyncResult1.在 System.ServiceModel.Channels.ReliableChannelBinder 的1.InputAsyncResultOnInputComplete(IAsyncResult 结果) 1.在 System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult 结果) 在 System.Runtime.AsyncResult.Complete(Boolean completedSynchronously) 在 System 的 OnInputCompleteStatic(IAsyncResult 结果) .Runtime.InputQueue 1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue1.EnqueueAndDispatch(Ite​​m item, Boolean canDispatchOnThisThread) at System.Runtime.InputQueue 1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread) at System.ServiceModel.Security.SecuritySessionClientSettings1.ClientSecurityDuplexSessionChannel.CompleteReceive(IAsyncResult result) at System.ServiceModel.Security.SecuritySessionClientSettings1.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.SecuritySessionClientSettings1.ClientSecuritySessionChannel.ReceiveAsyncResult.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, 异常异常)在 System.ServiceModel.Channels.ReliableChannelBinder 1.InputAsyncResult1.OnInputComplete(IAsyncResult 结果) 在 System.ServiceModel.Channels.ReliableChannelBinder 1.InputAsyncResult1.OnInputCompleteStatic(IAsyncResult 结果) 在 System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult 结果) 在 System.Runtime .AsyncResult.Complete(Boolean completedSynchronously) 在 System.Runtime.InputQueue1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue1.Dispatch() 在 System.Runtime.InputQueue`1.OnDispatchCallback(Object state) 在 System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) 在 System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame (UInt32 错误,UInt32 bytesRead,NativeOverlapped* nativeOverlapped)在 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode,UInt32 numBytes,NativeOverlapped* pOVERLAP)

内部异常:System.NullReferenceException

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

StackTrace:在 System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext) 在 System.Web.HttpApplication.ThreadContext.Enter(Boolean setImpersonationContext) 在 System.Web.AspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback 回调,对象状态) 在 System.Web.AspNetSynchronizationContext。 CallCallback(SendOrPostCallback callback, Object state) at System.Web.AspNetSynchronizationContext.Post(SendOrPostCallback callback, Object state) at System.ServiceModel.Dispatcher.ThreadBehavior.BindCore(MessageRpc& rpc, Boolean startOperation) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4 (MessageRpc&rpc)

有谁有想法吗?

4

1 回答 1

0

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

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

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

于 2013-01-28T14:41:59.050 回答