2009-12-13 3 views
1

Я использую следующие 2 метода. Метод, называемый DoMyWork1, действительно хорошо масштабируется, так как требуется 6 секунд для запуска трех из них в 3 потоках. В то время как метод DoMyJob вообще не масштабируется. Если один поток занимает 4 секунды, для запуска 3 потоков требуется 13 секунд. Что я делаю не так? Чтение и/или запись файла требует специальной обработки потоков, отличной от пула потоков?vs2008 C#: вопрос пула потоков

Моего код вызова

public static void Process(MyDelegate md , int threads) 
{ 
    int threadcount = threads; 

    ManualResetEvent[] doneEvents = new ManualResetEvent[threadcount]; 

    DateTime dtstart = DateTime.Now; 

    List<string> myfiles = GetMyFiles(@"c:\"); 


    for (int i = 0; i < threadcount; i++) 
    { 

     doneEvents[i] = new ManualResetEvent(false); 
     MyState ms = new MyState(); 
     ms.ThreadIndex = i; 
     ms.EventDone = doneEvents[i]; 
     ms.files = myfiles; 
     ThreadPool.QueueUserWorkItem(md.Invoke, ms); 
    } 


    WaitHandle.WaitAll(doneEvents); 

    DateTime dtend = DateTime.Now; 
    TimeSpan ts = dtend - dtstart; 
    Console.WriteLine("All complete in {0} seconds.", ts.ToString()); 
    Console.ReadLine(); 

} 

public static void DoMyWork1(Object threadContext) 
{ 
    MyState st = (MyState)threadContext; 
    Console.WriteLine("thread {0} started...", st.ThreadIndex); 

    Thread.Sleep(5000); 

    Console.WriteLine("thread {0} finished...", st.ThreadIndex); 
    st.EventDone.Set(); 
} 



private static void DoMyJob(MyState st) 
{ 
    Console.WriteLine("I am in thread {0} started...", st.ThreadIndex); 


    string[] mystrings = new string[] { "one", "two", "three" }; 

    foreach (string s in mystrings) 
    { 
     foreach (string file in st.files) 
     { 
      if (!(new StreamReader(file).ReadToEnd().Contains(s))) 
      { 
       AppendToFile(String.Format("{0} word searching in file {1} in thread {2}", s, file, st.ThreadIndex)); 
      } 


     } 
    } 

    Console.WriteLine("I am in thread {0} ended...", st.ThreadIndex); 
} 
+0

Можете ли вы добавить код, используемый для отправки тем? –

+0

public static void Process (MyDelegate md, int threads) { int threadcount = threads; ManualResetEvent [] doneEvents = new ManualResetEvent [threadcount]; ДатаTime dtstart = DateTime.Теперь; Список myfiles = GetMyFiles (@ "c: \"); для (int i = 0; i

ответ

2

Темы могут улучшить программный перфоманс только в том случае, если программа вышла из строя для ресурсов ЦП. Это не относится к вашей программе, она должна быть легко видна на вкладке Производительность Taskmgr.exe. Медленным ресурсом здесь является ваш жесткий диск или сетевая карта. Вызов ReadToEnd() медленный, медленный, ожидая, пока диск будет извлекать данные файла. Все, что вы делаете с данными файла, легко на 3 порядка быстрее, чем это.

Потоки будут просто ждать очереди данных диска. Фактически, есть хороший шанс, что потоки фактически заставят вашу программу работать намного медленнее. Они заставят головку дисковода прыгать назад и вперед между несвязанными дорожками на диске, так как каждый поток работает с другим файлом. Единственное, что есть действительно slow заставляет голову искать другую дорожку. Обычно около 10 мсек для быстрого диска. Эквивалент примерно полмиллиона инструкций ЦП.

Вы не можете заставить свою программу работать быстрее, если вы не получите более быстрый диск. SSD - это хорошо. Остерегайтесь эффектов кеша файловой системы, во второй раз, когда вы запускаете свою программу, он будет работать очень быстро, когда данные файла будут извлечены из кеша вместо диска. Это редко случается в производственной среде.

0

Все доступ к файлам станет серийным в слое OS и вкручивается как таковой будет приводить именно то, что вы видите.

+0

есть ли способ многопоточной обработки файлов? –

+0

Я не верю, что это правильно (доступ к файлам всегда последователен), хотя я не знаю точно, что вы подразумеваете под «serial» в этом контексте. Конечно, вы можете иметь два потока, одновременно выполняющих файл IO. Очевидно, что голова на диске может быть только над одной частью пластинки за раз, но аппаратное обеспечение и ОС обычно делают довольно хорошую работу, чтобы это не было проблемой. – Bruce

+0

http://stackoverflow.com/questions/93834/when-is-multi-threading-not-a-good-idea http://objectmix.com/smalltalk/761155-multi-threaded-file-access.html Это были мои источники. , y spi –

0

Я немного удивлен - я ожидаю, что первый доступ к этим файлам будет кэш, а затем оставшийся доступ просто ударит память. поэтому три потока не должны быть слишком медленными, чем один. Если вы пишете в каждый файл, это будет иметь значение - что именно делает функция AppendToFile?

0

Одной из проблем может быть то, что вы открываете и читаете каждый файл, для каждой новой строки, которую вы ищете.

Что произойдет, если вы измените порядок ваших циклов foreach и приложите их только к файлу по мере необходимости?

Думаю, вы увидите гораздо лучшую производительность.

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