locked
Remoting timeout issues

    Question

  • Are there any known workarounds for the really annoying lengthy remoting timeouts on down servers? This is particularly a problem when using .Net remoting and the server isn't available, it can take up to 2-3 minutes for the line of code to timeout when accessing a remote object.

    I have tried implementing a Ping class before I access the object, but sometimes this just doesn't work if the server is in the process of shutting down...

    Obviously having an application hang for that long is unacceptable.. I am threading everything however my application will not cleanly close if the thread is hung waiting for a socket timeout.

     

    A sample for you..


    ClassExample myclass = (ClassExample)Activator.GetObject(typeof(ClassExample),"tcp://someserver:65000/RemoteObject");

    if(myclass.IsAlive){    // HANGS here if remoting can't contact server for remote object.

    myclass.Dosomething();

    }

    Sunday, November 05, 2006 9:25 PM

Answers

  • We "solved" this proble like this:

    The remoting server has a Method called Ping() wich just returns the current DateTime on the server (it would probably also work if this method doesn't return anything at all). On the remoting client we call Server.Ping() inside an extra thread. If the method didn't return after a certain time or an exception is thrown, the thread is aborted and we know the remoting connection is not available, and hence the server can be considered being offline. This is probably more expensive that opening an extra socket for pinging but really makes sure that not only the sever application is running/the server machine is up but also that the actual remoting connection can be established.



    // Ping the server in its own thread (so it doesn't block)

    Exception pingException = null;
    DateTime now = DateTime.Now;
    System.Threading.
    Thread pingThread = new System.Threading.Thread(delegate()
    {
      try
      {
        this.lastServerReply = this.remoteAdapter.Ping();
      }
      catch (Exception ex)
      {
        pingException = ex;
      }
    });
    pingThread.Start();
    if (pingThread.Join((int)this.pingWaitTime.TotalMilliseconds))
    {
      if (pingException == null)
      {
        // no exception was thrown and the thread was not aborted
        // so we know that the remoting connection is available
      }
    }

     

    Thursday, January 11, 2007 2:47 PM

All replies

  • The HTTP and TCP channel has timeout property that you can configure.

    - Vipul

    Monday, November 06, 2006 5:18 AM
  • I've tried setting the timeout property in the channel via code, but it doesn't work at all. Doesnt seem to work on HTTP Channels either. I've seen references to it working (url here), but its not. I'm using the 2.0 framework (2.0.50727). Here's a code snippet (that times out after 3 minutes when remote server is turned off):

    int configport = 65001;
    string configserver = "server01";
    BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
    BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();

    serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
    IDictionary props = new Hashtable();
    props[
    "port"] = 0;
    string s = System.Guid.NewGuid().ToString();
    props[
    "name"] = s;
    props[
    "typeFilterLevel"] = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
    props[
    "timeout"] = 2000;  // also tried connectionTimeout

    TcpChannel chan = new TcpChannel(props, clientProvider, serverProvider);
    //HttpChannel chan = new HttpChannel(props, clientProvider, serverProvider);
    ChannelServices.RegisterChannel(chan, false);

    MyObject remoteObject = (MyObject)Activator.GetObject(typeof(MyObject), String.Format("tcp://{1}:{0}/RemoteObject", configport, configserver));
    if (remoteObject.childObject != null) { }    // Throws an exception when server unavailable, timeout takes 3 minutes!

     

    Sunday, November 26, 2006 10:39 PM
  • can you set both timeout and connectionTimeout properties and let us know the results.

    http://DotNetWithMe.blogspot.com
    vikas goyal

    Monday, November 27, 2006 4:25 AM
  • Sorry I keep forgetting to check this thread.. yea I tried both, and a few other things.. I had another developer tackle it as well but he found the same results. There's no apparent way to have .Net timeout connections to proxy's that don't exist (i.e. Server is completely offline)

    The only workable solution (which I think is a horrible way to do it) is to ping the server before making a request. If the ping times out, assume it's not available to make a connection. Of course the standard exception catching is still needed in case it's not hosting the object. This isn't terribly efficient, I'm just really suprised such an integrated part of .Net doesn't have a connection timeout implemented. If I'm wrong, point it out because no one I've introduced this to has been able to come up with a better solution.

    Friday, December 29, 2006 11:35 PM
  • Rather than using .IsAlive why dont you write a Ping method at server, where you can just return "true".

    sKumar

    Friday, January 05, 2007 2:55 AM
  • Does anyone know of a good solution to this issue? 

    A ping solution doesn't work because the machine may be available but the host containing the required object may not be running.

    A general connection timeout property doesn't seem to be supported in .Net 2.0 when using a TCPChannel or HTTPChannel.  The documentation only lists a connectionTimeout property for the IPCChannel.

    Thanks...

     

    Tuesday, January 09, 2007 9:42 PM
  • correct, if the machine is in the process of booting then a ping solution could give funny results. If the machine is up and simply not hosting the object (for whatever reason) than it will timeout very quickly and throw an exception, however if the machine cannot respond then your client application hangs for a while...

    In case anyone is interested, the timeout seems to be around 45 seconds, almost exactly. The IPCChannel does contain a working timeout however it's no good for network communications obviously.

    Thursday, January 11, 2007 7:11 AM
  • Thanks for the reply...

    It's the 45 second initial timeout that not acceptable in my situation, and I would assume this is a bit long for any application. 

    I'm going to try to asynchronously open a raw TCP sockect connection to the TCPChannel on the server and use an AutoResetEvent and WaitOne with my own specified timeout.  This will at least let me know the object is available for .Net remoting without having to wait the 45 seconds.  I'll simply close the raw socket connection if a connection is established.

     

    Thursday, January 11, 2007 2:25 PM
  • We "solved" this proble like this:

    The remoting server has a Method called Ping() wich just returns the current DateTime on the server (it would probably also work if this method doesn't return anything at all). On the remoting client we call Server.Ping() inside an extra thread. If the method didn't return after a certain time or an exception is thrown, the thread is aborted and we know the remoting connection is not available, and hence the server can be considered being offline. This is probably more expensive that opening an extra socket for pinging but really makes sure that not only the sever application is running/the server machine is up but also that the actual remoting connection can be established.



    // Ping the server in its own thread (so it doesn't block)

    Exception pingException = null;
    DateTime now = DateTime.Now;
    System.Threading.
    Thread pingThread = new System.Threading.Thread(delegate()
    {
      try
      {
        this.lastServerReply = this.remoteAdapter.Ping();
      }
      catch (Exception ex)
      {
        pingException = ex;
      }
    });
    pingThread.Start();
    if (pingThread.Join((int)this.pingWaitTime.TotalMilliseconds))
    {
      if (pingException == null)
      {
        // no exception was thrown and the thread was not aborted
        // so we know that the remoting connection is available
      }
    }

     

    Thursday, January 11, 2007 2:47 PM
  • I do something similar to this, but it's a bit nasty to do if you have a large application that does alot of remoting. Granted it works, but still... any MS guys wanna chirp in on this subject?
    Friday, January 12, 2007 2:28 AM
  • So... was this problem ever solved or addressed by Microsoft?
    Tuesday, November 27, 2007 11:18 AM
  • Nope it seems no one really paid attention to the issue. It still exists and the only known workaround is to ping the server beforehand. I constantly get the answer "but it is supported, check the remotingtimeout property" but of course that has been tested to death and does not deal with the issue at all.

    Tuesday, November 27, 2007 3:40 PM

  • Hi, All:

    SocketPro at www.udaparts.com has three connection, receiving and sending timeouts for this type of problems. Why don't you give it a try?

    Cheers


    Wednesday, November 28, 2007 3:23 PM
  • I have the same problem.

    When the timeout is set to less than 45 seconds, the SocketException is thrown as the setting.

    But when the timeout is set to more than 45 seconds, it is thrown in 45 seconds.

     

    Why?

    Does anyone know about this?

    Wednesday, March 05, 2008 10:25 AM
  • Still no solution?
    -Chris
    Wednesday, August 20, 2008 8:44 PM
  • Still nothing?  Pinging the server is not a bad idea, but that assumes your using multiple machines.  In my case, I am remoting between apps on the same machine.

    Is this going to be fixed?

    -Scott
    Thursday, October 30, 2008 10:32 PM
  • I ended up just opening a socket and trying to connect to the remote port (even if it was local) and used the connect timeout on the socket etc. etc.

    This has worked really well for me.

    -Chris
    Friday, March 13, 2009 8:48 PM
  • I found this KB - http://support.microsoft.com/kb/923614

    Apparently theres a hotfix floating around out there that allows the TCPChannel clas in .NET 1.1 to have a Timeout setting applied to it. Where the heck is the hotfix?

    It tells me to contact MS support to obtain it. Really? Then prompting me for payment method?

    MS... please just post a link to download the hotfix so I can move onto something else........
    -Chris
    Friday, August 07, 2009 7:53 PM
  • Is there any solution to this issue yet? 4 years later..
    Thursday, June 24, 2010 2:55 PM
  • I found one.

    If you don't name the channel via a property, you will have the 45 or so second timeout wait.

    If you name the channel, then you get the timeout you specify

    Make sure your channel name is unique.

    I started putting fun things like process id, thread id, and a random number in, since I attempt reconnect logic should the server for the client go down.

     

    Thursday, March 03, 2011 9:15 PM
  • Thanks
    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
     

    老徐的网站】:http://www.frankxulei.com/

    微软WCF中文技术论坛
    微软WCF英文技术论坛

    Windows Azure中文技术论坛

    Friday, March 25, 2011 9:07 AM
  • I found one.

    If you don't name the channel via a property, you will have the 45 or so second timeout wait.

    If you name the channel, then you get the timeout you specify

    Make sure your channel name is unique.

    I started putting fun things like process id, thread id, and a random number in, since I attempt reconnect logic should the server for the client go down.

     

    So this is correct solution? I haven't tryout yet, may be tomorrow.

    Thanks.

    Tuesday, March 29, 2011 2:39 PM
  • And how do you name the channel via a property??
    I need to try that.

    Thanks

    Monday, May 30, 2011 2:00 PM
  • Hello
    I also have that timeout problem.
    I have carefully read the thread but I get no solution.

    Could you please write down a few lines of code ...

    many thanks Peter

    Sunday, August 14, 2011 5:29 PM
  • Hello,

    MSDN is your friend ;). The code on the client-side:

    IDictionary props = new Hashtable() as IDictionary;
    props["name"] = "SomeFunnyName";
    props["timeout"] = 3000;
    props["connectionTimeout"] = 3000;
        
    m_Channel = new HttpClientChannel(props, new BinaryClientFormatterSinkProvider());               
    ChannelServices.RegisterChannel(m_Channel, false);

    I hope that helps.

    ThomasB.

    Monday, August 15, 2011 1:48 PM
  • Thank You

    unfortunately not.

    sorry, first i Tried TcpChannel ... I probably missed something in this trd.

    Now I Change to Http Channels

    BUT no effect. my Timeout remains at 40...120 seconds!!!!!!!
    I doubt even on myself... so I've copied your code... Unfortunately, no change.

    Any Ideas.
    Thank you

    • Proposed as answer by Misterfrederx Friday, December 09, 2011 6:39 PM
    • Unproposed as answer by Misterfrederx Friday, December 09, 2011 6:39 PM
    Tuesday, August 16, 2011 7:07 AM
  • I solve the problem (in my case)

    First: I have a server side application, a client and a dll (VB.net code). In the dll i wrote some code to connect database and then return the result via callback.

    I set all the remoting settings both server side and client side

    SERVER:

    Dim serverProv = New BinaryServerFormatterSinkProvider()
    
    serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full
    
    Dim clientProv = New BinaryClientFormatterSinkProvider()
    
    Dim props As IDictionary = New Hashtable()
    
    props.Add("port", 8080)
    
    props.Add("name", "icoServer")
    
    props.Add("timeout", -1) <-- dont work
    
    Dim ch As TcpChannel = New TcpChannel(props, clientProv, serverProv)
    
    Channels.ChannelServices.RegisterChannel(ch, False)
    
    ENGINE = New Queuer <-- the DLL class
    
    Dim ref As ObjRef = RemotingServices.Marshal(ENGINE, "dbEngine")
    
    

     CLIENT :

            Dim serverProv = New BinaryServerFormatterSinkProvider()
            serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full
    
            Dim clientProv = New BinaryClientFormatterSinkProvider()
    
            Dim props As IDictionary = New Hashtable()
            props.Add("name", "icoClient")
            props.Add("port", 12345)
            props.Add("timeout", -1)
    
            Dim ch As TcpChannel = New TcpChannel(props, clientProv, serverProv)
    
            ChannelServices.RegisterChannel(ch, False)
    
            RemotingConfiguration.RegisterWellKnownClientType(GetType(hope.DB.Queuer), "tcp://192.168.1.18:8080/dbEngine")
    
            x = New Queuer
    
    

    Ok the problem was that when the sql command requires more then 30 seconds (more or less), i received a timeout exception on client.

    I tried set timeout property, but i discover that this is not listed as property(http://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.tcp.tcpchannel(v=VS.71).aspx)

    So i tried another approach to the DB connection (the hosted class)

    first was something like this

    Dim d As New SqlDataAdapter(currentZombie.getRequest.sqlCommand, conn)
    d.Fill(sqlTable)
    

    where "currentZombie.getRequest.sqlCommand" is the sql command, this is a synchronous approach.

    Then i use this

    com.Connection = conn
    com.CommandTimeout = 0
    com.CommandType = CommandType.Text
    com.CommandText = currentZombie.getRequest.sqlCommand
    
    If currentZombie.getRequest.sqlCommand.ToUpper.Contains("SELECT") Then
    
       'QUERY (anche se non è detto)
       sync = com.BeginExecuteReader()
       i = 1
    Else
    
       'COMMAND
       sync = com.BeginExecuteNonQuery()
       i = 2
    End If
    
    While Not sync.IsCompleted
    
       If bw.CancellationPending Then
          'ABORT OPERATION
          e.Cancel = True
          com.Cancel()
          i = 0
       End If
    End While
    
    Select Case i
    Case 1
       'QUERY
       sqlTable.Load(com.EndExecuteReader(sync), LoadOption.OverwriteChanges)
    
    Case 2
       'COMMAND
       i = com.EndExecuteNonQuery(sync)
    
    Case Else
       'ABORT
       sqlTable = Nothing
    End Select
    

    This way no timeout is generated!

    I guess the secret is in the threading

    If the remoting thread is busy, the server cant say to the client that it's still alive

    So keeping separete threads for remoting and operations should be the solution

    Sorry for my english :(  I hope this helps someone

    Friday, December 09, 2011 7:20 PM