Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Winforms 在GUI线程上加载和保存应用程序配置_Winforms_User Interface_Settings - Fatal编程技术网

Winforms 在GUI线程上加载和保存应用程序配置

Winforms 在GUI线程上加载和保存应用程序配置,winforms,user-interface,settings,Winforms,User Interface,Settings,在GUI应用程序中保存和加载用户/应用程序设置的常用方法如下所示: private void FormMain_Load(object sender, EventArgs e) { m_foo = Properties.Settings.Default.Foo; } private void FormMain_FormClosing(object sender, FormClos

在GUI应用程序中保存和加载用户/应用程序设置的常用方法如下所示:

private void FormMain_Load(object sender, EventArgs e)
{                                                     
    m_foo = Properties.Settings.Default.Foo;
} 

private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
    Properties.Settings.Default.Save();
}
乍一看,这似乎是合理的。但是,一旦考虑到保存和(隐式)加载操作(即磁盘I/O)中实际发生了什么,它就显得有点可疑。它是否违背了一般避免潜在长时间运行操作的原则,尤其是GUI线程上的I/O

我意识到,在绝大多数情况下,我们谈论的是位于本地硬盘上的非常小的文件,但我可以想出一些场景,在这些场景中,如果我真的愿意,操作将需要一些时间才能完成(磁盘处于休眠状态,磁盘处于压力之下,磁盘实际上是网络存储,等等)

而且,我也不清楚该怎么办。启动非常容易处理,在异步加载设置时禁用GUI。但是最后一场比赛呢?当然,我可以取消事件,异步保存,然后关闭它自己,但它会有点混乱,因为我需要照顾的情况下,用户试图关闭它之前,我完成了保存(所以我不启动另一个保存,或退出,在储蓄中等)。我甚至不确定它是否可以在其他框架中实现(至少是简单地实现),比如说GTK,在GTK中,OnDeleteEvent通常在太晚的时候使用。我想我可以启动一个前台线程并将其保存在那里,但用户可能会认为应用程序已关闭,并在实际保存设置之前再次运行它(而且,不管多个实例是否处于活动状态,都可能会产生其他后果)


我是应该担心这种情况,还是我想得太多了?

你想得太多了。可能基于保存设置速度较慢的假设。它不在Winforms应用程序中,您没有在移动设备上运行此应用程序。文件写入总是由文件系统缓存进行缓存,除了内存到内存的拷贝之外什么都没有。它们以内存总线速度运行,最慢时为5千兆字节/秒(旧的DDR2),通常约为35 GB/秒

在此之后,文件系统驱动程序将延迟地将更改写入磁盘,并进行了高度优化,以最小化写入头的移动。在现代机器上最多可写入1GB的数据,如果有足够的RAM,则可写入更多数据。一个简单的6个数量级,比你需要的user.config文件要多


任何将其转换为异步写入的优化都无法使应用程序的响应速度超过毫秒,这是人类完全无法观察到的。这也是System.Configuration不支持的原因。你没有真正的问题。

我认为你忘记了一般规则的“为什么”(这是所有一般规则的危险)。“通常避免可能长时间运行的操作,特别是GUI线程上的I/O”原则背后的“原因”是在用户交互中保持响应性(低延迟)。如果您在GUI线程中执行长时间运行的工作,那么您的GUI将不会快速刷新

在应用程序加载(准备运行之前)或关闭(无法再与之交互)时,需要哪些用户交互?有些情况下,当有一个合法的答案时(与此应用程序中的另一个窗口交互等),但这只是少数时间


此外,这里还有各种缓冲区可以帮助缓解任何延迟。在应用程序调用配置读取之前(不一定),该文件可能会被读入磁盘缓冲区。磁盘输出只需转到最近的缓冲区,应用程序即可关闭。

谢谢,这样就可以保存配置了。加载它怎么样?您是否同意异步操作在启动时有意义(如上所述更容易实现)?嗯,这是一个非常不同的问题。它在应用程序启动时加载。以及在启动时发生的许多其他事情,包括在磁盘上查找程序集和jitting代码。只需再查找和读取一个文件,几十个文件中的一个。程序员倾向于使用启动屏幕来隐藏这种开销。如果这真的让您感到困扰,那么答案不在System.Configuration中。因此,您是说磁盘无论如何都可以访问,但从理论上讲,我的程序集可以在唤醒的D驱动器上,而我的配置可以在休眠的C驱动器上。在不同的线程上简单地使用
System.Configuration
有什么错(在加载时禁用控件)?嗯,你不太可能用禁用的UI而不是闪屏给用户留下深刻印象。如果你想继续这样做,那就试试吧,我对此没什么可说的。只要它被禁用并且没有卡住(例如,UI线程是免费的),你可能会说感知性能甚至比初始屏幕更好。在绝大多数情况下,它的速度会非常快,以至于用户不会注意到,无论是启动屏幕还是其他(至少对于这个特定的操作)。有意义吗?没有任何理由让非响应表单出现“应用程序未响应”对话框、启动或其他情况。我甚至可以在表单显示之前加载配置来规避这一问题,但这带来了一个更糟糕的问题,即用户在加载所有内容并显示表单之前完全看不到任何事情发生(这可能会导致他一次又一次地尝试打开应用程序)。当配置加载到另一个线程中时,我仍然喜欢禁用的UI(或者像Hans建议的那样,在有意义的初始屏幕上)。