3
\$\begingroup\$

I have a server-client environment, where the client connects and synchronizes data with the server every 5 second.

For synchronizing I use a background thread on the client which works fine, but on one specific hardware the method GetNetworkAvailable throws out of memory exceptions occasionaly. The errors occur whitout logic, so I guess somethings just not good with this hardware. Anyways I'd like to get your opinion on my background - polling function.

private void SynchronizedWorker()
{
    bool initialization = true;
    int initializationTries = 0;

    // Sync loop
    while (!_shouldStop)
    {
        // Initialize locals
        int syncInterval = _syncInterval; // Reset Sync Interval to default
        SyncStatus syncStatus = SyncStatus; // Get current Status
        bool hasNetworkConnection = true; // Has Network connection

        try
        {
            //*******************************************
            // Check Network connection
            //*******************************************
            if (!NetworkInterface.GetIsNetworkAvailable())
            {
                hasNetworkConnection = false;
                _syncResetEvent.Set();
                syncStatus = SyncStatus.Offline;
            }
            else if (syncStatus == SyncStatus.Offline) // Is in offline - State, but Network available again recognize going online
            {
                _syncResetEvent.Set();
                hasNetworkConnection = IsServiceAvailable();
                // Sync-Status stays offline
                if (!hasNetworkConnection)
                {
                    // Wait 1 minute, before retry
                    syncInterval = 60000;
                }
            }

            //*******************************************
            // Proceed with Syncronisation
            //*******************************************
            if (hasNetworkConnection)
            {
                syncStatus = SyncStatus.Ok;
                // Try Initialization
                if (initialization)
                {
                    try
                    {
                        // Sync initialization here...
                        // ..............................
                        ////////////////////////////////////
                    }
                    catch (Exception ex)
                    {
                        log.LogError(string.Format("Initialization Try {0}", initializationTries), ex);
                        syncStatus = SyncStatus.InitializationFailed;
                    }
                }

                // To many Init-Tries --> Stop
                if (initializationTries > 1)
                {
                    // Proceed
                    _syncResetEvent.Set();
                    _syncStatus = syncStatus;
                    break; // Stop Synch
                }

                // Debug
                var sw = System.Diagnostics.Stopwatch.StartNew();

                // Do Up/Download
                if (!initialization)
                {
                    try
                    {
                        // Synchronisation with service here...
                        // ..............................
                        ////////////////////////////////////

                        // Proceed
                        _syncResetEvent.Set();
                    }
                    catch (Exception ex)
                    {
                        log.LogError("Download", ex);
                        syncStatus = SyncStatus.SynchFailed;
                    }
                }
            }

            // Set Sync status
            _syncStatus = syncStatus;
        }
        catch (Exception ex)
        {
            log.LogError("Sync-Worker", ex);
            _syncStatus = Core.Sync.SyncStatus.SynchFailed;
            // Proceed
            _syncResetEvent.Set();
            // Reset Force
            _syncForce = false;
        }
        finally
        {
            // Set Completed
            if (OnSyncCompleted != null)
            {
                OnSyncCompleted(downloaded, uploaded, executed);
            }

            // Always Wait for Interval
            DateTime sleepuntil = DateTime.Now.AddMilliseconds(syncInterval);
            while (sleepuntil > DateTime.Now && !_shouldStop && !_syncForce)
            {
                // Sleep
                Thread.Sleep(100);
            }
        }
    }

    // Stop
    _syncStatus = SyncStatus.Unknown;
 }
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$
  1. I would do the waiting for interval at the end also with an event - I find it cleaner. Something like this:

    AutoResetEvent _syncWaitEvent = new AutoResetEvent(false);
    
    ....
    
    // I assume there is a way for external callers to stop sync
    public void StopSync()
    {
        _syncForce= true;
        _syncWaitEvent.Set();
    }
    
    public void ForceSync()
    {
        _shouldStop = true;
        _syncWaitEvent.Set();
    }
    
    private void SynchronizedWorker()
    {
        ....
        // Sync loop
        while (!_shouldStop)
        {
            ....
    
            // wait for next interval or being woken up
            if (_syncWaitEvent.WaitOne(syncInterval))
            {
                // we have been signaled prior to the timeout expiring
                _syncForce = false;
            }
        }
    }
    
  2. I would change syncInterval to a TimeSpan (WaitOne() expects one anyway and I don't like passing values around with implicit units. Just gets you in trouble some day)

  3. It's not clear from your code what the _syncResetEvent() is used for. It's seems to be called in pretty much every case. You might want to revisit the name of it.

  4. Add a log message in the if (initializationTries > 1) block to state that you are stopping sync because init failed too many times.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.