Re: Intermittent Remoting Event Callback Problem

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Sam Santiago (ssantiago_at_n0spam-SoftiTechture.com)
Date: 08/03/04


Date: Mon, 2 Aug 2004 23:24:31 -0700


    I have seen articles on MSDN stating that creating and destroying many
objects can become a performance issue and garbage collection issue, so you
might want to consider a singleton if possible. You might want to use a
tool like Lutz Roeder's .NET Reflector, http://www.aisto.com/roeder/dotnet,
to see if you can find more information as to why your exception is being
thrown by looking into the System.Net.Sockets.Socket.Connect method.
    Good luck.

Thanks,

Sam

-- 
_______________________________
Sam Santiago
ssantiago@n0spam-SoftiTechture.com
http://www.SoftiTechture.com
_______________________________
"Mike Hacker" <MikeHacker@discussions.microsoft.com> wrote in message
news:7F5DF90E-CC2B-47D0-8F12-EED7C95C0443@microsoft.com...
> 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!
> > >
> > >
> >
> >
> >


Relevant Pages

  • Re: Intermittent Remoting Event Callback Problem
    ... MarshalByRefObj created using the New statement and returned to the client ... a SAO resulting in a callback to a "proxy"/wrapper class. ... to the server upon disconnection. ... reqMsg, IMessage retMsg) ...
    (microsoft.public.dotnet.distributed_apps)
  • Re: Custom COM callbacks
    ... a COM server cleanup connections to a client if the client crashes". ... I have an out of process COM server that provides notifications of events to ... clients via a custom callback interface. ... call Release on the callback interfaces, ...
    (microsoft.public.vc.atl)
  • RE: Controls not updated by callback event
    ... In a client callback, a client script function sends a request to the ... Another function receives the result from the server code ... Microsoft Online Community Support ...
    (microsoft.public.dotnet.framework.aspnet.buildingcontrols)
  • Re: Non-blocking notification mechanism via RMI
    ... The remote software would provide the callback object to the server. ... If you are saying that you don't want to use a remote callback mechanism then there really isn't much you can do but block. ... Another approach is to have the server post answers to a client specific queue and have the client periodically remotely dequeue answers. ...
    (comp.lang.java.programmer)
  • Re: Basic .net remoting question
    ... In case of later proxys are created at the client side and any ... > objets and server activated objects. ... > CAO ... Single-Call and Singleton. ...
    (microsoft.public.dotnet.framework.remoting)