[英]invoke WCF using wsDualHttpBinding
我有一個獨立的應用程序,它將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.ProcessMessage31(MessageRpc&rpc)處System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&rpc)位於System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageR。系統。在System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessageP(System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext請求,OperationContext currentOperationContext)在System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext請求,布爾cleanThread,OperationContext currentOperationContext) System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult結果)在System.Runtime.AsyncResult.Complete(布爾值已同步完成)在System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult結果)在System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult結果)
1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue
1.Dispatch()位於System.ServiceModel.Channels.ReliableDuplexSessionChannel.ProcessDuplexMessage(WsrmMessageInfo info)的System.ServiceModel.Channels.ClientReliableDuplexSessionChannel.ProcessMessage(WsrmMessageInfo info)的InputQueue1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue
System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsynce結果)的System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnReceiveCompletedStatic(IAsyncResult結果)處的System.ServiceModel.Channels.ReliableDuplexSessionChannel.HandleReceiveComplete(IAsyncResult結果)在System.Runtime.AsyncResult.Complete(布爾完成完成同步) 麻煩的是,System.ServiceModel.Channels.ReliableChannelBinder1.InputAsyncResult
1.System.ServiceModel.Channels.ReliableChannelBinder1.InputAsyncResult
1.OnInputCompleteStatic(IAsyncResult結果)位於System.Runtime.Fx.AsyncThunk。 System.Runtime.InputQueue處的System.Runtime.AsyncResult.Complete(布爾值已1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue
完成)的UnhandledExceptionFrame(IAsyncResult結果)System.Runtime.InputQueue處的1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue
處的UnhandledExceptionFrame(IAsyncResult結果) .Runtime.InputQueue1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread) at System.ServiceModel.Security.SecuritySessionClientSettings
1.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.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.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結果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.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
I(IAsyncResult結果) )在System.Runtime.AsyncResult.Complete(布爾值完成同步)在System.Runtime.AsyncResult.Complete(布爾值同步完成,異常異常)在System.Servicetime.AsyncResult.Complete(布爾同步完成,異常異常)在System.ServiceModel.Channels.ReliableChannelBinder1.InputAsyncResult
OnInputComplete(IAsyncResult結果)1.InputAsyncResult
1.System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult結果)位於System.Runtime.AsyncResult.Complete的1.InputAsyncResult
1.OnInputCompleteStatic(IAsyncResult結果) (布爾值1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue
完成)在System.Runtime.InputQueue1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue
1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue
1.System.Runtime.InputQueue的1.Dispatch(1.AsyncQueueReader.Set(Item item) at System.Runtime.InputQueue
1.OnDispatchCallback(Object state)(UInt32 errorCode,UInt32 numBytes,NativeOverlapped * nativeOverlapped) System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode,UInt32 numBytes,NativeOverlapped * pOVERLAP)的System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32錯誤,UInt32字節讀取,NativeOverlapped * nativeOverlapped)InnerException:System.NullReferenceException
消息:對象引用未設置為對象的實例。
StackTrace:在System.Web.HttpApplication.ThreadContext.Enter(在System.Web.HttpApplication.OnThreadEnterPrivate(布爾setImpersonationContext)在System.Web.AspNetSynchronizationContext.CallCallbackbackPossfullyUnderLock(SendOrPostCallback回調,對象狀態)在System.Web.AspNetSynchronization System.Web.AspNetSynchronizationContext.Post(SendOrPostCallback回調,對象狀態)處於System.ServiceModel.Dispatcher.ThreadBehavior.BindCore(MessageRpc&rpc,Boolean startOperation)處於System.ServiceModel.Dispatcher.ImmutableDispatchRun4.CallCallback(SendOrPostCallback回調,對象狀態) (MessageRpc&rpc)
有人有什么主意嗎?
您的Windows客戶端在wsDualHttpBinding
工作,因為WCF能夠在客戶端和WCF服務之間創建持久會話 ,該會話在給定的超時時間內持續存在。
ASP.NET是一個服務器端框架,它從指定的應用程序池中抓取線程來處理傳入的HTTP請求,創建HTTP響應,然后將該線程返回給應用程序池。 您遇到的問題是,當從ASP.NET代碼中調用WCF服務時,ASP.NET將拆除任何wsDualHttpBinding
創建的會話(這不等同於ASP.NET會話)。 基本上,ASP.NET應用程序實例化一個WCF客戶端,該客戶端僅在HTTP請求/響應對期間存在,並且由於拆解過程而刪除了您的回調目標
要完成您描述的內容,您需要在ASP.NET上下文中實現一個獨立的wsDualHttpBinding
連接管理器。 我認為避免完全使用wsDualHttpBinding
綁定並創建一個簡單的基於令牌的輪詢消息模式來模擬回調機制會容易得多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.