Re: Intermittent Remoting Event Callback Problem

From: Mike Hacker (MikeHacker_at_discussions.microsoft.com)
Date: 08/02/04

  • Next message: Nick L.: "Re: No Touch Deploy Caching Issues"
    Date: Mon, 2 Aug 2004 09:11:02 -0700
    
    

    I apologize – that was evidence of a recent design change. There is an OPCEngine published component that was originally a singleton. It has a method on it called getInstance that returns an OPCServer object based on a stationID. There really was no reason to make the class-factory a singleton (that I could see – should I?), so it only lives for the lifetime of the call by a client to request an OPCServer object … on the server. (Hence my comment regarding the SAO.) So, to answer your question, it’s a SAO requested by the client through a single-call class factory. I’ve also overridden the lifetime services within OPCEngine to a lease time of 0 seconds – so it should be destroyed immediately. (Not sure if this is redundant, as singlecall may actually perform this indirectly for me. Wanted to insure it didn’t stick around for the default time of 5 minutes. I have verified this is working correctly by observing entries I’m making in a log file.)

    The solution works great 99% of the time; I just occasionally get an error calling back to a client when a call is made on the SAO’s delegate. It appears to only have happened after starting a new instance of the client…and is corrected by closing the application, and restarting it. The strange thing is that I have a worker thread that gets spun off to attempt to reconnect to the server and re-register the callbacks when an error occurs – which also happens as expected. BUT: After tearing down the remoting channel on the client, re-connecting (and calling the getinstance method on the OPCEngine object), the callback *STILL* fails. So I end up in a “reconnect loop” of sorts. Closing and re-opening the app makes everything work fine. So it appears as though the problem persists throughout the existing of the erroneous app-domain regardless of what’s done with the remoting channels/etc. Not sure what would cause that. Thanks.

    "Sam Santiago" wrote:

    > Here's another question. You have configured your OPCEngine object as
    > SingleCall:
    >
    > <wellknown mode="SingleCall" type="Sequoia.Manufacturing.OPCEngine,
    > OPCServer" objectUri="OPCEngine" />
    >
    > And based on this statement you appear to want a Singleton OPCServer object:
    >
    > m_oOPCServer = m_oOPCEngine.getInstance(m_sStationID);
    >
    > What type of object are you expecting m_oOPCServer to be? Did you want it
    > to be an SAO? A Singleton or Singlecall? If so, this will not work. Any
    > MarshalByRefObj created using the New statement and returned to the client
    > by a call to a remote object, in this case the m_oOPCEngine.getInstance
    > method, is treated as a CAO. Is this what you wanted?
    >
    > Thanks,
    >
    > Sam
    > --
    > _______________________________
    > Sam Santiago
    > ssantiago@n0spam-SoftiTechture.com
    > http://www.SoftiTechture.com
    > _______________________________
    > "Mike Hacker" <MikeHacker@discussions.microsoft.com> wrote in message
    > news:47F119E2-B162-4B0D-9669-17432F1FB724@microsoft.com...
    > > Hello,
    > >
    > > I have been experiencing occasional problems when calling a delegate from
    > a SAO resulting in a callback to a "proxy"/wrapper class. Upon startup, the
    > "client" (understandably running as a server when a callback occurs) is
    > successfully (in all cases - even when the issue occurs) able to connect and
    > make calls to methods on the SAO. After connecting, the "client" creates a
    > worker thread that periodically makes a call to a "ping" method on the SAO;
    > which in turn invokes a callback to the client.a sort of 2-way heartbeat
    > that was needed to permit the "client" the ability to monitor and reconnect
    > to the server upon disconnection. Here's a diagram:
    > >
    > >
    > >
    > > Client --> Creates Proxy object to interact with SAO
    > >
    > > --> Connects to Server
    > >
    > > <-- Server Factory generates object
    > >
    > > --> Proxy registers callback to server ping delegate
    > >
    > > --> Proxy generates monitor thread to periodically
    > "ping" the server
    > >
    > > .dwell (loop begin)
    > >
    > > --> Proxy calls ping method on server - proxy dwells for a
    > >
    > > Response from the server
    > >
    > > <-- Server invokes client_ping delegate
    > >
    > > .. If proxy receives a response, the loop starts again.
    > >
    > >
    > >
    > > Here's the problem: Occasionally -- On startup (after the channel is
    > programmatically registered), everything is successful, and the client
    > invokes the SAO's ping method, but when the server attempts to invoke the
    > proxy's callback method, it fails with the following exception:
    > >
    > >
    > >
    > > [07/29/2004 09:39:23:9985 AM] Severity: 0 -
    > OPCServer::FireDataChangeEvent-->Client Unreachable...Details:
    > System.Net.Sockets.SocketException: No connection could be made because the
    > target machine actively refused it
    > >
    > >
    > >
    > > Server stack trace:
    > >
    > > at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
    > >
    > > at System.Runtime.Remoting.Channels.RemoteConnection.CreateNewSocket()
    > >
    > > at System.Runtime.Remoting.Channels.SocketCache.GetSocket(String
    > machineAndPort)
    > >
    > > at
    > System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.SendRequestWithR
    > etry(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream)
    > >
    > > at
    > System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.AsyncProcessRequ
    > est(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders
    > headers, Stream stream)
    > >
    > > at
    > System.Runtime.Remoting.Channels.BinaryClientFormatterSink.AsyncProcessMessa
    > ge(IMessage msg, IMessageSink replySink)
    > >
    > >
    > >
    > > Exception rethrown at [0]:
    > >
    > > at
    > System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage
    > reqMsg, IMessage retMsg)
    > >
    > > at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
    > msgData, Int32 type)
    > >
    > > at Sequoia.Manufacturing.DataChangeHandler.EndInvoke(IAsyncResult
    > result)
    > >
    > > at Sequoia.Manufacturing.OPCServer.CallbackComplete(IAsyncResult ar)
    > >
    > > at
    > System.Runtime.Remoting.Messaging.AsyncResult.SyncProcessMessage(IMessage
    > msg)
    > >
    > > at
    > System.Runtime.Remoting.Messaging.AsyncReplySink.SyncProcessMessage(IMessage
    > reqMsg)
    > >
    > > at
    > System.Runtime.Remoting.Channels.BinaryClientFormatterSink.AsyncProcessMessa
    > ge(IMessage msg, IMessageSink replySink)
    > >
    > > at
    > System.Runtime.Remoting.Messaging.ClientContextTerminatorSink.AsyncProcessMe
    > ssage(IMessage reqMsg, IMessageSink replySink)
    > >
    > > at
    > System.Runtime.Remoting.Messaging.EnvoyTerminatorSink.AsyncProcessMessage(IM
    > essage reqMsg, IMessageSink replySink)
    > >
    > > at
    > System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvokeAsync(IMessageSi
    > nk ar, Message reqMsg, Boolean useDispatchMessage, Int32 callType)
    > >
    > > at
    > System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(IMethodCallMess
    > age reqMcmMsg, Boolean useDispatchMessage, Int32 callType)
    > >
    > > at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(IMessage
    > reqMsg)
    > >
    > > at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
    > msgData, Int32 type)
    > >
    > > at Sequoia.Manufacturing.DataChangeHandler.BeginInvoke(tPlcDataResult
    > PlcData, AsyncCallback callback, Object object)
    > >
    > > at Sequoia.Manufacturing.OPCServer.FireDataChangeEvent(tPlcDataResult
    > DataChangeResult)
    > >
    > >
    > >
    > > I'm using the .config file on the Server component (service) with the
    > class factory generating the SAO's, and programmatically registering the
    > channel on the "client" (as I need to be able to tear down the channel and
    > re-create it when an error occurs - something that can't be done if you use
    > Remoting.configure.) Here's what the "servers" config file looks like:
    > >
    > >
    > >
    > > <system.runtime.remoting>
    > >
    > > <customErrors mode="off" />
    > >
    > > <application name="Sequoia">
    > >
    > > <service>
    > >
    > > <wellknown mode="SingleCall"
    > type="Sequoia.Manufacturing.OPCEngine, OPCServer" objectUri="OPCEngine" />
    > >
    > > </service>
    > >
    > >
    > >
    > > <channels>
    > >
    > > <channel ref="tcp" name="IO Server" port="1999"
    > useIpAddress="true">
    > >
    > > <clientProviders>
    > >
    > > <formatter ref="binary" />
    > >
    > > </clientProviders>
    > >
    > > <serverProviders>
    > >
    > > <formatter ref="binary"
    > typeFilterLevel="Full" />
    > >
    > > </serverProviders>
    > >
    > > </channel>
    > >
    > > </channels>
    > >
    > > </application>
    > >
    > > </system.runtime.remoting>
    > >
    > >
    > >
    > > Here's the code I'm using on the client to create the channel:
    > >
    > >
    > >
    > > System.Collections.IDictionary properties = new
    > System.Collections.Hashtable();
    > >
    > > properties["name"] = "OPCProxyClient::" +
    > m_sStationID + "::"
    > >
    > > + System.Guid.NewGuid().ToString();
    > >
    > > properties["port"] = 0;
    > >
    > > properties["useIpAddress"] = true;
    > >
    > >
    > >
    > > BinaryServerFormatterSinkProvider serverProvider
    > >
    > > = new BinaryServerFormatterSinkProvider();
    > >
    > >
    > >
    > > BinaryClientFormatterSinkProvider clientProvider
    > >
    > > = new BinaryClientFormatterSinkProvider();
    > >
    > >
    > >
    > > serverProvider.TypeFilterLevel =
    > System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
    > >
    > >
    > >
    > > oChan = new TcpChannel(properties, clientProvider,
    > serverProvider);
    > >
    > > ChannelServices.RegisterChannel(oChan);
    > >
    > >
    > >
    > > // Casting to the class factory
    > >
    > > // interface, and having it generate a new OPCServer object
    > >
    > > // for us
    > >
    > > Sequoia.Manufacturing.iOPCEngine m_oOPCEngine =
    > (iOPCEngine)
    > >
    > >
    > System.Runtime.Remoting.RemotingServices.Connect(typeof(iOPCServer)
    > >
    > > , m_sServerURL + "/Sequoia/OPCEngine");
    > >
    > >
    > >
    > > m_oOPCServer =
    > m_oOPCEngine.getInstance(m_sStationID);
    > >
    > >
    > >
    > > // This line instructs the SAO to start // it's work
    > >
    > > bool bStartResult=m_oOPCServer.Start();
    > >
    > >
    > Sequoia.Manufacturing.Util.WriteLogMessage("OPCProxy -- OPCServer Start
    > Result: " + bStartResult
    > >
    > > + " Station: " + m_sStationID,1,false);
    > >
    > >
    > >
    > > m_oOPCServer.OnPLCDataChange += new
    > DataChangeHandler(m_oOPCServer_OnPLCDataChange);
    > >
    > > m_oOPCServer.OnServerShutdown += new
    > OPCServerShutdown(m_oOPCServer_OnServerShutdown);
    > >
    > > // Here's my ping callback registration
    > >
    > > m_oOPCServer.OnPingCallback += new
    > OPCServerEvent(m_oOPCServer_OnPingCallback);
    > >
    > >
    > >
    > > One interesting thing, both in our client's installation, and in our
    > "sterile" office environment, we're not using DNS - and are (from our
    > understanding of the channel objects) taking advantage of the useIPAddress -
    > could this intermittent behavior be caused by the "server" object not being
    > able to "see" the client to make the callback? Any assistance would be
    > appreciated!
    > >
    > >
    >
    >
    >


  • Next message: Nick L.: "Re: No Touch Deploy Caching Issues"

    Relevant Pages

    • Re: Intermittent Remoting Event Callback Problem
      ... > in fact, it's not just the ping callback - as you can see from the code, ... > est(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders ... > ge(IMessage msg, IMessageSink replySink) ... > reqMsg, IMessage retMsg) ...
      (microsoft.public.dotnet.distributed_apps)
    • Intermittent Remoting Event Callback Problem
      ... Client --> Creates Proxy object to interact with SAO ... at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink) ... at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) ...
      (microsoft.public.dotnet.distributed_apps)