[英]Enum.TryParse - is it thread safe?
我試圖弄清楚.NET 4.0的Enum.TryParse是否是線程安全的。
源代碼(反編譯)是:
[SecuritySafeCritical]
public static bool TryParse<TEnum>(string value, bool ignoreCase, out TEnum result) where TEnum : struct
{
result = default(TEnum); /// (*)
Enum.EnumResult enumResult = default(Enum.EnumResult);
enumResult.Init(false);
bool result2;
if (result2 = Enum.TryParseEnum(typeof(TEnum), value, ignoreCase, ref enumResult))
{
result = (TEnum)enumResult.parsedEnum;
}
return result2;
}
對我來說似乎有問題的是這一行:
result = default(TEnum); /// (*)
如果另一個線程在將其設置為默認值之后,並且在將其設置為已解析值之前訪問結果,該怎么辦?
[編輯]按照Zoidberg的回答,我想稍微改一下這個問題。
問題是,我想,如果Enum.TryParse是“事務性的”(或原子的)。
假設我有一個靜態字段,並將其傳遞給Enum.TryParse:
public static SomeEnum MyField;
....
Enum.TryParse("Value", out MyField);
現在,當執行TryParse時,另一個線程訪問MyField。 TryParse會將MyField的值更改為SomeEnum的默認值一段時間,然后才會將其設置為已解析的值。
這不一定是我的代碼中的錯誤。 我希望Enum.TryParse能夠將MyField設置為已解析的值,或者根本不觸摸它,而不是將其用作臨時字段。
result
,與所有其他局部變量和參數,是每個呼叫。 by-ref參數的線程安全性要稍微復雜一些,但是:在每個合理的用法中 - 這都不是問題。 我可以強制它有風險的場景(由於by-ref傳遞),但這將是一個人為的例子。
典型用法:
SomeEnumType foo;
if(Enum.TryParse(s, true, out foo)) {...}
非常安全。
以下有點復雜:
var objWithField = new SomeType();
// thread 1:
{
Enum.TryParse(x, true, out objWithField.SomeField));
}
// thread 2:
{
Enum.TryParse(y, true, out objWithField.SomeField));
}
並且不是線程安全的,但是比你在問題中描述的那些更微妙的原因。
是的。
在您反編譯的方法中根本沒有共享狀態。
如果另一個線程調用相同的方法,它將獲得它自己的所有本地副本,並且result
由調用者傳入。
如果result
是類級變量,那么這將是一個問題,但這很好。
結果(因此它引用的變量)可以變為默認值(T),盡管字符串值包含不同的枚舉值,如果它是你的意思。
嘗試以下程序:
public enum FooBar
{
Foo = 0,
Bar
}
internal class Program
{
private static FooBar fb = FooBar.Bar;
private static void Main()
{
new Thread(() =>
{
while (true)
{
if (Program.fb == FooBar.Foo) // or try default(FooBar), which is the same
{
throw new Exception("Not threadsafe");
}
}
}).Start();
while (true)
{
if (!Enum.TryParse("Bar", true, out fb) || fb == FooBar.Foo)
{
throw new Exception("Parse error");
}
}
}
}
它遲早(可能更早)拋出“Not threadsafe”異常。
這不是TryParse是否是線程安全的問題,而是使用它的代碼(您的代碼)是否是線程安全的。 如果您傳入結果變量,然后讓另一個線程訪問它而沒有一些互斥保護,那么您可能會遇到問題,但問題出在您的代碼中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.