2015-09-05 2 views
3

У меня есть следующий код, который два потока добавляет новые элементы в список.Как следующий код автоматически защищен потоком?

public class Numbers 
     { 
      public int number; 
      public string threadName; 
     } 
     static void Main(string[] args) 
     { 

      List<Numbers> numbers = new List<Numbers>(); 

      Task t = Task.Factory.StartNew(() => { 
       for (int i = 0; i < 999; i++) 
       { 
        numbers.Add(new Numbers() { number = i, threadName = "t" }); 

       } 
      }); 
      Task k = Task.Factory.StartNew(() => 
      { 
       for (int i = 0; i < 999; i++) 
       { 
        numbers.Add(new Numbers() { number = i, threadName = "k" }); 
       } 
      }); 


      t.Wait(); 
      k.Wait(); 


      StreamWriter writer = new StreamWriter("text.txt"); 

      foreach (var item in numbers) 
      { 
       writer.WriteLine(item.threadName + item.number); 
      } 
      writer.Flush(); 
      Console.WriteLine("Done!"); 
      Console.ReadLine(); 
     } 

Когда я открываю текстовый файл, я вижу их идеально выровнены с k0k1 ... k999t0t1 ... t999. Но я ожидал, что список будет смешанным или перетасованным. Почему эти две задачи не добавляют новые элементы случайным образом, но вместо этого они сортируются отлично?

+0

Возможно, потому что ваши задачи заканчиваются _very_ быстро, а первый заканчивается до того, как второй настроен? Не то, что 'List ' в любом случае не является потокобезопасным, поэтому, как только вы выполняете обе задачи, выполняемые по-настоящему параллельными, вы получите исключения, которые выбраны из 'Add()'. – CodeCaster

+0

@CodeCaster Вы всегда правы. Я добавил немного потока сна после добавления элемента и да, они непредсказуемы. – ozgur

ответ

2

Ваши задачи определенно не являются потокобезопасными, потому что они одновременно записываются в один список. Наиболее вероятная причина, по которой вы получаете результаты, которые вы видите, состоит в том, что первая задача выполняется очень быстро - она ​​заканчивает запись всех 999 объектов до того, как вторая задача получит шанс начать.

Если вы добавите случайную короткую задержку к выполнению своей задачи, вы увидите некоторую случайность результатов. Если вы делаете больше задач, скорее всего, добавите некоторую случайность: например, если вы сделаете свой список List<string> и построите свои строки по ходу, вторая задача может начаться до завершения первого.

+0

Задача 'k' никогда не будет выполняться до окончания' t'. –

+1

@ M.kazem Я так не думаю. 'Task.Factory.StartNew()' запускает задачу немедленно. 'Wait()' s находятся там, поэтому код только _ заканчивается после завершения обеих задач. – CodeCaster

+0

@ M.kazemAkhgary Это обязательно начнется и может закончиться. (['TaskFactory.StartNew' документация] (https://msdn.microsoft.com/en-us/library/dd321439%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396)). – dasblinkenlight

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