c# threading issue RRS feed

  • Question

  • I am using custom client connection for 10 tcp clients.  

    bool _flagScanner1Connect = true; private xyzTranmissionProtocol xyz1TranmissionProtocol = null; private static readonly object LockWhileConnectingForScanner1 = new object(); internal ICustomClient Scanner1Conn; System.Threading.Timer _tmrCheck1ClientConn; public void Start1ScannerConn() { try { _tmrCheck1ClientConn = new System.Threading.Timer(Check1ScannerConn, null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(5)); } catch (Exception ) { } } private void Check1ScannerConn(object state)

    { if (!_flagScanner1Connect) return;

    lock (LockWhileConnectingForScanner1) {

    if (Scanner1Conn == null || Scanner1Conn.CommunicationState == ClientCommunicationStates.Disconnected) {

    try { _tmrCheck1ClientConn.Change(Timeout.Infinite, Timeout.Infinite); Scanner1Conn = CustomClientFactory.CreateClient(new CustomClientTcpEndPoint(“Scanner IpAdress”, “Scanner Port Number”)); Scanner1Conn.Connected += Scanner1Conn_Connected; ; Scanner1Conn.Disconnected += Scanner1Conn_Disconnected; Scanner1Conn.MessageReceived += Scanner1Conn_MessageReceived; xyz1TranmissionProtocol = new xyzTranmissionProtocol(); Scanner1Conn.TransmissionProtocol = xyz1TranmissionProtocol; Scanner1Conn.Connect(); //SEND A PING MESSAGE _tmrCheck1ClientConn.Change(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5)); } catch (Exception ) { if (_flagScanner1Connect) try { Scanner1Conn?.Disconnect(); } catch { } try { Scanner1Conn?.Dispose(); } catch { } try { Scanner1Conn = null; } catch { } } finally { _tmrCheckClientConn.Change(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5)); } } } }

    I have written 10 different functions for 10 bar code scanners. above code is for 1 scanner.  if i use 3 scanners  or less than 3 my application will work. but if i use more than 3 scanners then message received events will not work And  the application will become very slow. can anyone help me out to solve this issue.

    Friday, June 29, 2018 10:28 AM

All replies

  • I don't know that the issue is with threading although it could be. Your connection management just seems wrong to me. You call a client factory to create a client. Does this always create a new client or does it potentially return an existing one?

    You are mucking with your timer's interval a lot - why? You're using a Threading.Timer so it is reentrant. It is possible that while you're running this code that it calls back again, hence your code isn't timer safe. Your Check1ScannerConn method seems to be the method that is run when the timer expires so you're in the middle of handling this event when you change the interval to 5 seconds. Depending upon how long that code takes to execute you may have already called back into this method again. The lock at the top prevents you from entering the code but it is still blocking the timer thread. Basically the longer your code runs the more likely you are to eat up the thread pool threads while blocked waiting for the previous request to complete. This is not going to scale at all. The more scanners you add the faster it is going to be until you run out of thread pool threads to run against.

    Shortly after changing the timer to 5 seconds you then set it to 5 seconds again so this final code seems redundant. Don't muck with the timer interval at all. Use a simple variable to manage reentrancy with perhaps a double check to handle race conditions.

    One of the things you should decide is the lifetime of the scanner. In your code you are treating the scanners as short lived. But you're hooking up events to them. Since you never unhook those events the scanners are going to be around longer than you think. Short-lived objects generally shouldn't need event handlers. If the scanners are shared entities then creating and destroying them may make sense here but then the events probably don't. If the creation of the scanners is expensive then it might be better to create them up front and reuse them for the life of your app. Only you can decide which is the approach to go. I'm going to assume that irrelevant you have a CreateScanner method that does this creation and returns back the scanner for your use. To replicate your existing code I would do this.

    //Since we don't have a consistent scanner object we'll have to create a sync object ourselves
    private Mutex _lckScanner1 = new Mutex(false);
    private void Check1ScannerConn ( object state )
       //Check for reentrancy and abort
       if (!_lckScanner1.WaitOne(1))
          using (var scanner = CreateScanner())
             //Does this do the actual ping??
       } finally

    If you instead decide to create the scanners up front then a lot of this "scanner 1" specific stuff can be generalized down. The only thing your timer would do, beside the reentrant check, is the ping call.

    Michael Taylor

    Friday, June 29, 2018 2:23 PM