Search code examples
c#application-settingsmultiple-instances

Mutex not behaving as expected when loading Form settings


Based on an Code Project article on Windows Forms User Settings by David Veeneman, I have been playing around with saving the start location and start size of an application.

It works perfectly in the single instance, but when I expand it to multiple instance I run into problems.

I've wrapped the section dealing with loading the setting and saving the settings in a mutex to protect writing to and from the settings file.

I would like the windows to stack from the last known location. This seems to work fine most of the time, but if I open up four or five windows in rapid sucession the first three will open perfectly, then there will be a gap, and after that some of them start to open at the same location.

Render the Form/Application:

 private Mutex saveSetting;
 private const int START_LOCATION_OFFSET = 20;

 private void MainForm_Load(object sender, EventArgs e)
    {
        // Get the mutex before the reading of the location
        // so that you can't have a situation where a window drawn
        // in the incorrect position.

        this.saveSetting = new Mutex(false, "SaveSetting");
        this.saveSetting.WaitOne();

        this.LoadWindowStartSizeAndLocation();
        .
        .
        .
        .
        .

        this.saveSetting.ReleaseMutex();
    }

Loading the settings:

private void LoadWindowStartSizeAndLocation()
        {
            // Set window location
            if (Settings.Default.WindowLocation != null)
            {
                System.Drawing.Point startLocation = 
                  new System.Drawing.Point
                     (Settings.Default.WindowLocation.X + START_LOCATION_OFFSET,
                      Settings.Default.WindowLocation.Y + START_LOCATION_OFFSET);

                this.Location = startLocation;
                Settings.Default.WindowLocation = startLocation;

                Settings.Default.Save();
            }

            // Set window size
            if (Settings.Default.WindowSize != null)
            {
                this.Size = Settings.Default.WindowSize;
            }
        }

Saving the settings:

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        try
        {
            this.SaveWindowSizeAndLocationForNextStart();                
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.Assert(false, ex.Message);
        }
    }

    /// <summary>
    /// Save the Window Size And Location For the next Application Start up.
    /// </summary>
    private void SaveWindowSizeAndLocationForNextStart()
    {
        if (this.WindowState != FormWindowState.Minimized)
        {
            // Copy window location to app settings
            Settings.Default.WindowLocation = this.Location;
            Settings.Default.WindowSize = this.Size;
        }
        try
        {
            this.saveSetting = new Mutex(false, "SaveSetting");
            this.saveSetting.WaitOne();

           Settings.Default.Save();
        }
        catch
        {
            // Do nothing. It won't permanently disable the system if we
            // can't save the settings.
        }
        finally
        {
            this.saveSetting.ReleaseMutex();
        }
    }

Can anyone tell me what I'm doing worng? Or how based on the code above could I get two instances rendered to the same start location??

Thanks A


Solution

  • The problem is that settings are loaded before the mutex is acquired. Call Settings.Default.Reload() after acquiring the mutex.