Search code examples
thread-safetyapp-configread-write

IO error when accessing app.config from thread


I'm trying to write to my app.config from a thread using Task.Run(()=> method) but I'm getting an IO error on line 2 in the method below

"System.IO.IOException: 'The process cannot access the file 'WpfApplication1.exe.Config' because it is being used by another process.'"

private static void UpdateCustomConfigSection(string sectionName, string key, string val)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile); //Error happens here

            XmlNode selectSingleNode = xmlDoc.SelectSingleNode($"//{sectionName}/add[@key='{key}']");
            if (selectSingleNode != null && selectSingleNode.Attributes != null)
            {
               selectSingleNode.Attributes["value"].Value = val;
            }

            xmlDoc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

            ConfigurationManager.RefreshSection(sectionName);
        }

I assume this is happening because the main application thread is reading from the file and is blocking the thread from accessing it. Is there a recommended way to do this?


Solution

  • For work with app.config you should use ConfigurationManager.
    See example below:

        private static void UpdateCustomConfigSection(string key, string val)
        {
            Configuration configuration = ConfigurationManager.OpenExeConfiguration(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
            configuration.AppSettings.Settings[key].Value = val;
            configuration.Save();
            ConfigurationManager.RefreshSection("appSettings");
        }
    

    But if the problem is different thread you can use Dispatcher.Invoke.

            Dispatcher.Invoke(() =>
            {
                UpdateCustomConfigSection(sectionName,key, val);
            });
    

    In this case UpdateCustomConfigSection should be invokes in UI thread regardless of where Dispatcher.Invoke construction calls