我正在编写一个保存.NET应用程序设置的程序。所有这些都是用户范围而不是应用程序范围。代码在技术上有效,但非常脆弱和错误;有时它只保存部分设置而不是整个设置。由于这个错误,我经常需要重新输入所有配置数据,即使进行了微小的更改。
这个问题似乎是随机的 - 有时它会发生,有时则不会发生,所以我无法通过检测模式确定原因。但是,我已经注意到,如果我一次性重新输入所有数据然后单独留下它而不改变配置中的任何内容,应用程序通常会按预期方式工作。
正在编写的所有Properties.Settings.Default。*值都来自这些用户控件实例(pga,pl,pd等)中的参数。基本上,用户控件是在主Config类中一次显示一个页面(取决于用户从树菜单中选择的值)。来自用户控件的表单数据通过内部作用域参数公开给Config类。每个参数都匹配它对应的设置的数据类型 - 参数是完成值,因此生成它们的任何必要逻辑都发生在用户控件中。
这是应用程序保存/更新其配置数据的方式:
private void SaveConfig()
{
lock(saveLock){
try
{
Properties.Settings.Default.GatewayIP_Primary = pga.GatewayIP;
Properties.Settings.Default.AutoConnect = pg.AutoStart;
Properties.Settings.Default.TranslateOAI = pg.Translate;
Properties.Settings.Default.GatewayPort = pga.GatewayPort;
Properties.Settings.Default.MariaDBPort = pd.MariaDBPort;
Properties.Settings.Default.MariaDBPass = pd.MariaDBPass;
Properties.Settings.Default.MariaDBUser = pd.MariaDBUser;
Properties.Settings.Default.MariaDBHost = pd.MariaDBHost;
Properties.Settings.Default.SaveClearLog = pl.AutoSaveLog;
Properties.Settings.Default.LogSavePath = pl.LogFolderPath;
Properties.Settings.Default.SaveTime = pl.LogSaveTime;
Properties.Settings.Default.PulseFrequency = pg.PulseInterval;
Properties.Settings.Default.AutoNightMode = pn.AutoNightMode;
Properties.Settings.Default.NMSleep = pn.SleepTime;
Properties.Settings.Default.NMWake = pn.WakeTime;
Properties.Settings.Default.AdminExt = pn.NightModeAdminExt;
Properties.Settings.Default.TrunkAccessCode = pga.TrunkCode;
Properties.Settings.Default.LocalAreaCode = pg.LocalAreaCode;
Properties.Settings.Default.ExpandedExt = pga.UseExpandedExtensions;
Properties.Settings.Default.AllowDNDOverride = pg.DNDOverride;
Properties.Settings.Default.TollStation=pga.TollStation;
Properties.Settings.Default.MailboxNum=pga.MailboxPrefixCode;
Properties.Settings.Default.EmailRecipients = pe.RecipientList;
Properties.Settings.Default.EmailServer = pe.EmailHost;
Properties.Settings.Default.ShowBalloons = pg.ShowBalloon;
Properties.Settings.Default.EventThreshholdMinutes = pe.EventThreshhold;
Properties.Settings.Default.ConnectTimeout = pga.ConnectTimeout;
Properties.Settings.Default.UseGateway = pga.UseGateway;
Properties.Settings.Default.Save();
Properties.Settings.Default.Reload();
}
catch (Exception ex)
{
string err = "Encountered a problem whilst updating settings: " + ex.ToString();
Reporter.WritetoSystemLog(err, 0);
}
finally
{
// Refresh the preferences.
BufferTools t = new BufferTools();
t.LoadSettings();
MainWindow.main.AddtoLog("Refreshed configuration data.");
}
}// end of lock
Close();
}
起初,我认为竞争条件导致表单在所有值保存之前关闭,所以我尝试将代码放在今天早些时候的锁中。然而,这没有帮助。
此外,我只在项目文件夹中的debug / release目录中运行此程序。这仍然是一项正在进行中的工作,尚未准备好部署。可能与它有关吗?也许频繁的构建对保存的设置做了一些事情。
有关可能导致此问题的任何想法?
编辑:这是在启动期间(重新)将数据从配置加载到内存中的代码。该应用程序使用Buffer。*值来代替所有内容,而不是直接触摸配置。此代码是BufferTools类的一部分,而不是Config:
//################################################################################################
/// <summary>
/// Load the config data into buffer. This should run when the program starts up
/// and whenever the user refreshes the config. --Will Kraft (8/31/15).
/// </summary>
/// <returns>Load result.</returns>
///
internal bool LoadSettings(){
try
{
Buffer.LastEventReceived = DateTime.Now;
Buffer.appVersion = Properties.Settings.Default.Version;
Buffer.GatewayIP_Primary = Properties.Settings.Default.GatewayIP_Primary;
Buffer.GatewayIP_Secondary = Properties.Settings.Default.GatewayIP_Secondary;
if (!string.IsNullOrEmpty(Properties.Settings.Default.GatewayPort))
Buffer.GatewayPort = System.Convert.ToInt32(Properties.Settings.Default.GatewayPort);
Buffer.ClientPort = System.Convert.ToInt32(Properties.Settings.Default.ClientPort);
Buffer.AutoConnect = Properties.Settings.Default.AutoConnect;
Buffer.TranslateOAI = Properties.Settings.Default.TranslateOAI;
Buffer.TrunkAccessCode = Properties.Settings.Default.TrunkAccessCode;
Buffer.AdminExt = Properties.Settings.Default.AdminExt;
if (!string.IsNullOrEmpty(Properties.Settings.Default.DialOutNum))
Buffer.DialOutNum = Int32.Parse(Properties.Settings.Default.DialOutNum);
Buffer.NeedsDialOutNum = Properties.Settings.Default.NeedsDialOutNum;
Buffer.MariaDBHost = Properties.Settings.Default.MariaDBHost;
Buffer.MariaDBUser = Properties.Settings.Default.MariaDBUser;
Buffer.MariaDBPass = Properties.Settings.Default.MariaDBPass;
Buffer.MariaDBPort = Properties.Settings.Default.MariaDBPort;
Buffer.LogLocation = Properties.Settings.Default.LogSavePath;
Buffer.CleanupTimeStr = Properties.Settings.Default.SaveTime;
Buffer.AutoSave = Properties.Settings.Default.SaveClearLog;
Buffer.AutoNightMode = Properties.Settings.Default.AutoNightMode;
Buffer.WakeTimeStr = Properties.Settings.Default.NMWake;
Buffer.SleepTimeStr = Properties.Settings.Default.NMSleep;
Buffer.cleanupHourMinute = Properties.Settings.Default.SaveTime;
Buffer.ExpandedExt = Properties.Settings.Default.ExpandedExt;
//Buffer.PulseInterval = System.Convert.ToDecimal(Properties.Settings.Default.PulseFrequency);
Buffer.PulseInterval = Properties.Settings.Default.PulseFrequency;
Buffer.PhoneSystemType = Properties.Settings.Default.SystemType;
Buffer.MailboxNumber = Properties.Settings.Default.MailboxNum;
Buffer.TollRestrictStation = Properties.Settings.Default.TollStation;
Buffer.AllowDNDOverride = Properties.Settings.Default.AllowDNDOverride;
Buffer.ShowBalloons = Properties.Settings.Default.ShowBalloons;
Buffer.EventTimeThreshhold = Properties.Settings.Default.EventThreshholdMinutes;
Buffer.ConnectTimeout = Properties.Settings.Default.ConnectTimeout;
Buffer.LocalAreaCode = Properties.Settings.Default.LocalAreaCode;
Buffer.MailHost = Properties.Settings.Default.EmailServer;
if (Buffer.PulseInterval == 0)
Buffer.PulseInterval = 1.0f;
// load email recipients list. --Will Kraft (10/30/15).
Buffer.EmailRecipients = new List<string>();
Buffer.EmailRecipients.Clear();
string[] addresses = Properties.Settings.Default.EmailRecipients
.Split(Constants.BRIDGE_SEP);
foreach (string addr in addresses)
{
if(!string.IsNullOrWhiteSpace(addr))
Buffer.EmailRecipients.Add(addr);
}
// Set maintenance timers.
//SchedulerCore.SetupTimerEvents();
string configPath = ConfigurationManager.
OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath;
Reporter.WritetoSystemLog("Configuration/settings file path: " + configPath, 2);
}
catch (ConfigurationErrorsException ex)
{
string err="The configuration file has syntax errors or is corrupt.";
if (MainWindow.main != null)
{
MainWindow.main.ShowEventMessage(err, 0);
}
Reporter.WritetoSystemLog(err + "\r\n\r\nDetails:\r\n" + ex.ToString(), 0);
}
catch (Exception e)
{
Reporter.WritetoSystemLog("Configuration did not load. Details: " + e.ToString(), 0);
return false;
}
return true;
}