【问题标题】:invoke WCF using wsDualHttpBinding使用 wsDualHttpBinding 调用 WCF
【发布时间】:2013-01-26 12:39:04
【问题描述】:

我有一个独立的应用程序,它使用带有 wsDualHttpBinding 的 WCF。 这个独立的应用程序会通过wsDualHttpBinding的回调行为,随机向任何订阅了该服务的客户端发送消息。

如果我们使用窗口应用程序作为客户端,应用程序的订阅和回调行为是成功的。

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

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

以下是 SignalR 的 hub 代码

 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

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

堆栈跟踪:在 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 当前操作上下文)在 System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext 请求,OperationContext currentOperationContext)在 System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult 结果)在 System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult 结果)在 System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult 结果)在 System.Runtime.AsyncResult.Complete(布尔 同步完成)在 System.Runtime.InputQueue1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue1.Dispatch() 在 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(布尔 同步完成)在 System.Runtime.AsyncResult.Complete(布尔完成同步, 异常异常)在 System.ServiceModel.Channels.ReliableChannelBinder1.InputAsyncResult1.OnInputComplete(IAsyncResult 结果)在 System.ServiceModel.Channels.ReliableChannelBinder1.InputAsyncResult1.OnInputCompleteStatic(IAsyncResult 结果)在 System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult 结果)在 System.Runtime.AsyncResult.Complete(布尔 同步完成)在 System.Runtime.InputQueue1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue1.EnqueueAndDispatch(Ite​​m item, Boolean canDispatchOnThisThread) 在 System.Runtime.InputQueue1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread) at System.ServiceModel.Security.SecuritySessionClientSettings1.ClientSecurityDuplexSessionChannel.CompleteReceive(IAsyncResult 结果)在 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 结果)在 System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult 结果)在 System.Runtime.AsyncResult.Complete(布尔 同步完成)在 System.Runtime.AsyncResult.Complete(布尔完成同步, 异常异常)在 System.ServiceModel.Channels.ReliableChannelBinder1.InputAsyncResult1.OnInputComplete(IAsyncResult 结果)在 System.ServiceModel.Channels.ReliableChannelBinder1.InputAsyncResult1.OnInputCompleteStatic(IAsyncResult 结果)在 System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult 结果)在 System.Runtime.AsyncResult.Complete(布尔 同步完成)在 System.Runtime.InputQueue1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue1.Dispatch() 在 System.Runtime.InputQueue`1.OnDispatchCallback(对象状态)在 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)

InnerException: System.NullReferenceException

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

堆栈跟踪:在 System.Web.HttpApplication.ThreadContext.Enter(布尔 setImpersonationContext) 在 System.Web.HttpApplication.OnThreadEnterPrivate(布尔值 setImpersonationContext) 在 System.Web.AspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback 回调,对象状态)在 System.Web.AspNetSynchronizationContext.CallCallback(SendOrPostCallback 回调,对象状态)在 System.Web.AspNetSynchronizationContext.Post(SendOrPostCallback 回调,对象状态)在 System.ServiceModel.Dispatcher.ThreadBehavior.BindCore(MessageRpc& rpc,布尔 startOperation)在 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)

有人知道吗?

【问题讨论】:

    标签: asp.net wcf signalr


    【解决方案1】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-04
      相关资源
      最近更新 更多