簡體   English   中英

Enum.TryParse - 它是線程安全的嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM