FloatToStr / DateToStr 的线程安全性
我刚刚在文档中发现 FloatToStr
和 DateToStr
在其单参数重载中不是线程安全的。原因是它们访问存储在全局变量中的本地化信息。
我的问题是:如果我不在运行时更改格式设置,这有任何实际意义吗?据我了解,只要每个人都只读取格式设置(即使是从多个线程),我就是安全的。
这是真的还是我在这里遗漏了一些东西?
谢谢。
I just found in the documentation that FloatToStr
and DateToStr
are not thread-safe in their one-paramater overloads. The reason is that they access localization information stored in global variables.
My question is: is this of any practical relevance if I do not change the format settings at runtime? As far as I understand it, I'm on the safe side as long as everyone only reads the format settings - even from multiple threads.
Is that true or am I missing something here?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
FloatToStr、DateToStr 和其他类似函数正在读取全局格式设置。因此,如果您的应用程序不更改这些函数调用的这些设置,那么它就是线程安全的。相反的以下代码不是线程安全的:
当您需要胎面安全和“本地”格式设置时,您必须使用重载函数,该函数作为最后一个参数:AFormatSettings:TFormatSettings。因此,为了使上述代码线程安全,您必须编写:
注意:
FloatToStr, DateToStr and others similar functions are reading global format settings. So, if your application does not change these settings for these function calls, then it is thread safe. The following code on opposite is not thread safe:
When you need the tread safety and "local" format settings, then you have to use overloaded functions, which take as last parameter: AFormatSettings: TFormatSettings. So, to make above code thread safe you have to write:
Notes:
当 Application.UpdateFormatSettings(Delphi 7,不知道 Delphi XE)为 True 时,甚至全局设置也可以更改。当用户更改 Windows 的区域和语言选项时,这将反映在您的应用程序中。您可以通过将 UpdateFormatSettings 设置为 False 来规避此问题,但即使这样您也不能确定,也许您使用的某些第三方库会更改它。
我在我们自己的应用程序中遇到了一些问题:在我们的应用程序中,全局格式设置没有任何更改,但仍然存在信息丢失,因为浮点数被转换为字符串,当字符串转换回浮点数时,格式设置被神奇地改变了。 (所以你有这个: 1.2 -> 转换为字符串 -> '1.2' -> 改变 formatsettings.decimalseparator 的黑魔法 -> 转换为浮点 -> 12)。
我的建议:仅将非线程安全版本用于 UI 目的,以便用户看到日期并按照他喜欢的方式浮动,对于其他所有内容,请使用线程安全版本。应用程序内的转换将保持一致,不会产生意外。
Even the global settings can change when Application.UpdateFormatSettings (Delphi 7, don't know about Delphi XE) is True. When a user changes the Regional and Language options of Windows, this will be reflected in your application. You can circumvent this by setting UpdateFormatSettings to False, but even then you can't be sure, maybe there is some third party library you use that changes it.
I had some problems with our own application: Nowhere in our application the global formatsettings were changed, but still there was information loss because a float was converted to a string and when the string was converted back to float, the formatsettings were magically changed. (So you had this: 1.2 -> convert to string -> '1.2' -> black magic that changed formatsettings.decimalseparator -> convert to float -> 12).
My suggestion: only use the not thread-safe version for UI purposes so the user sees dates and floats the way he likes them to see, for everything else, use the thread-safe version. Conversions inside your application will then be consistent and don't give surprises.
如果在执行
FloatToStr
或DateToStr
时全局设置没有被另一个线程更改,那么就没有问题。编辑:要记住的一件事:
上面的全局变量只是下面列出的全局变量的别名。可以通过
FormatSettings
变量或直接更改它们。If the global settings are not changed by another thread while
FloatToStr
orDateToStr
are executed you are fine.EDIT: one thing to keep in mind:
The global variable above is just an alias for the global variables listed below. It is possible to change them either through the
FormatSettings
variable or directly.我只是遇到了小数点分隔符的问题。 Delphi 的流系统(readcomponent/writecomponent 等)只需将其更改为“.”当所有工作完成后,它又变回原来的样子。
因此,当我将这个系统用于我自己的目的(序列化/反序列化相当复杂的结构)并决定在单独的线程中甚至在几个单独的线程中执行它时,它让我大吃一惊:“。”在某处与“,”混合。
不幸的是,我在其他一些库中看到,当 DecimalSeparator 在过程中简单地更改时,打算在最后将其更改回来(最仔细的库将其放在“finally”子句中),因此,如果您的某些代码在这些库之一被执行在单独的线程中运行,使用 StrToFloat 等线程安全版本是必要的。
I just had problem with decimal separator. Delphi's streaming system (readcomponent/writecomponent etc) simply changes it to '.' and after all the work is done, it is changed back to whatever it was.
So, when I used this system for my own purposes (serializing/deserializing rather complex structure) and decided to do it in separate thread, or even in several separate threads, it shot me to the leg: '.' were mixed with ',' somewhere.
Unfortunately, I saw in some other libraries when DecimalSeparator is simply changed in procedure with intention to change it back at the end (most careful ones put it in 'finally' clause), so if some of your code is executed when one of these libs are running in separate thread, using thread-safe versions of StrToFloat etc. is imperative.