2016-11-24 6 views
0

У меня есть несколько массивов типа char [] и string [], которые определяются как «static readonly». Их предметы никогда не меняются.Threadsafety and foreach со статическими массивами readonly

Перечисления 'foreach' и 'generics' являются потокобезопасными?

private static readonly string[] staticReadOnlyArray = new string[] { "someKey0", "someKey1", "someKey2", ... }; 

public bool SomeThreadSharedCall(string toCheck) 
{ 
    // #1 
    foreach (string s in staticReadOnlyArray) 
    { 
     if (s == toCheck) 
      return true; 
    } 
    return false; 

    // #2 
    return staticReadOnlyArray.Contains(toCheck); 

    // or #3 
    return staticReadOnlyArray.Any(s => string.Compare(toCheck, s, StringComparison.OrdinalIgnoreCase) == 0); 

    // or #4 
    staticReadOnlyArray.ForEach(s => someAction(s, toCheck)); 
} 

ответ

0

Операции в вашем методе являются «потоковыми» только на основании вашего утверждения, что Their items never change.; однако ничто в данном коде не гарантирует этого.

Термин threadsafe обычно используются для обозначения, что код в вопросе гарантирует, что данные не изменятся, или если он может изменения, операция будет по-прежнему производить правильные результаты.

Вам необходимо будет выполнить your own synchronization logic, чтобы сделать код действительно потоковым.

=== Ответ на Ваши комментарии:

Возвращаемое значение GetEnumerator() - то, что вы звоните iterator - сам по себе безопасен для исключительного использования вызывающим потоком, но это не проблема. Это базовая коллекция (массив), которая не является потокобезопасной, потому что она может измениться.

Замена foreach на цикл for не делает код более надежным. Вам нужно либо синхронизировать доступ к коллекции, либо сделать ее неизменной.

В вашем случае я предлагаю последнему указать, что данные в вашем массиве постоянны. Чтобы сделать его конкретным для вас, вот какой-то концептуальный код:

private static readonly IEnumerable<string> staticReadOnlyData = Array.AsReadOnly(new string[] { "someKey0", "someKey1", "someKey2", ... }); 

public bool SomeThreadSharedCall(string toCheck) 
{ 
    // #1 
    foreach (string s in staticReadOnlyData) 
    { 
     if (s == toCheck) 
      return true; 
    } 
    return false; 

    // #2 
    return staticReadOnlyData.Contains(toCheck); 

    // or #3 
    return staticReadOnlyData.Any(s => string.Compare(toCheck, s, StringComparison.OrdinalIgnoreCase) == 0); 
} 
+0

Спасибо за ответ. Я ясно понимаю многопоточность API Win32 на C++. Но я смутился с C# 4. Массив IEnumerable. Для перемещения используется ссылка IEnumerator iterator = array.GetEnumerator(). Итак, итератор ссылается на новую копию IEnumerator , или каждый поток получает ссылку на одну копию объекта итератора? В последнем случае у нас есть проблема. – Yargo

+0

Все, что мне нужно - это постоянный предопределенный массив и поточно-безопасный метод для поиска. У меня есть дилемма - переписать код из 'foreach' в' for (int i = 0; i Yargo

0

Лучший способ, если вы не уверены, - проверить его! Но да, они потокобезопасны.

Смежные вопросы