1

wsDualHttpBindingでWCFを使用しているスタンドアロンアプリケーションがあります。このスタンドアロンアプリケーションは、wsDualHttpBindingのコールバック動作を使用して、サービスをサブスクライブしているすべてのクライアントにランダムにメッセージを送信します。

ウィンドウアプリケーションをクライアントとして使用すると、アプリケーションのサブクライブとコールバックの動作は正常に機能します。

次に、SignalRをサーバープッシュとして使用するASP.Netアプリケーションを作成し、上記のスタンドアロンアプリケーションによって提供されるサービスをサブスクライブします。アプリケーションからメッセージが返ってきたら、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: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 .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 System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request、Boolean cleanThread、System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request、OperationContext currentOperationContext)at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)at System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)at System .Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)at System.Runtime.AsyncResult.Complete(BooleancompletedSynchronously)at System.Runtime.InputQueueSystem.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)at System.Runtime.AsyncResult.Complete(BooleancompletedSynchronously)atSystem.Runtime.InputQueueのDispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)at System.Runtime.AsyncResult.Complete(BooleancompletedSynchronously)atSystem.Runtime.InputQueueのDispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result)1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue1.System.ServiceModel.Channels.ReliableDuplexSessionChannel.ProcessDuplexMessage(WsrmMessageInfo info)at System.ServiceModel.Channels.ClientReliableDuplexSessionChannel.ProcessMessage(WsrmMessageInfo info)at System.ServiceModel.Channels.ReliableDuplexSessionChannel.HandleReceiveComplete(IAsyncResult result)atSystem。 ServiceModel.Channels.ReliableDuplexSessionChannel.OnReceiveCompletedStatic(IAsyncResult result)at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)at System.Runtime.AsyncResult.Complete(Boolean completeSynchronously)at System.Runtime.AsyncResult.Complete(Boolean completeSynchronously、Exception例外)System.ServiceModel.Channels.ReliableChannelBinderで1.InputAsyncResult1.OnInputComplete(IAsyncResult result)at System.ServiceModel.Channels.ReliableChannelBinder 1.InputAsyncResult1.OnInputCompleteStatic(IAsyncResult result)at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)at System.Runtime.AsyncResult.Complete(Boolean completeSynchronously)at System .Runtime.InputQueue 1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue1.EnqueueAndDispatch(Item 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 completeSynchronously)at System.Runtime.AsyncResult.Complete(Boolean completeSynchronously、Exception例外)at System.ServiceModel.Channels.ReliableChannelBinder 1.InputAsyncResult1.OnInputComplete(IAsyncResult result)at System.ServiceModel.Channels.ReliableChannelBinder 1.InputAsyncResult1.OnInputCompleteStatic(IAsyncResult result)at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)at System.Runtime System.Runtime.InputQueueの.AsyncResult.Complete(BooleancompletedSynchronously)1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue1.System.Runtime.InputQueueのDispatch() `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(Boolean setImpersonationContext)at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)at System.Web.AspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback、Object state)atSystem.Web.AspNetSynchronizationContext。 System.ServiceModel.Dispatcher.ThreadBehavior.BindCore(MessageRpc&rpc、Boolean startOperation)at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4のSystem.Web.AspNetSynchronizationContext.Post(SendOrPostCallbackコールバック、オブジェクト状態)のCallCallback(SendOrPostCallbackコールバック、オブジェクト状態) (MessageRpc&rpc)

誰かが何か考えを持っていますか?

4

1 に答える 1

0

WCF は、クライアントと WCF サービスの間で一定のタイムアウト期間持続する永続的なセッションwsDualHttpBindingを作成できるため、Windows クライアントは で動作します。

ASP.NET は、指定されたアプリ プールからスレッドを取得して着信 HTTP 要求を処理し、HTTP 応答を作成してそのスレッドをアプリ プールに返すサーバー側フレームワークです。あなたが抱えている問題は、ASP.NETコードから呼び出されたときにWCFサービスによってASP.NETwsDualHttpBindingが作成されたセッション(これはASP.NETセッションと同等ではありません)を破棄することです。基本的に、ASP.NET アプリは、HTTP 要求/応答ペアの間だけ存続する WCF クライアントをインスタンス化し、破棄プロセスの結果としてコールバック ターゲットが削除されます。

あなたが説明していることを達成するにはwsDualHttpBinding、ASP.NET コンテキスト内に独立した接続マネージャーを実装する必要があります。wsDualHttpBindingバインディングを完全に使用することを避け、単純なトークンベースのポーリング メッセージ パターンを作成してコールバック メカニズムをシミュレートする方がはるかに簡単だと思います。

于 2013-01-28T14:41:59.050 に答える