Всем привет. Бьюсь над мультипоточностью уже вторые сутки.
Заранее прошу меня извинить, описать проблему без приведения своего запутанного кода не смог.
В коде приведённом ниже открываются текстовые файлы и разделяются на неповторяющиеся слова. (различные слова)
В один поток все выполняется правильно и без ошибок.
Если запускаю столько потоков, сколько ядер процессора - то, при одинаковых исходных данных - в результате разное количество слов, что по определению невозможно. Либо ошибка (индекс вне границ массива).
Если кому-нибудь не лень разобраться в моём коде и указать на ошибку - буду весьма признателен.
Класс Program.cs - здесь вызываются потоки обрабатывающие файлы:
| Код | using System; using System.IO; using System.Text; using System.Threading;
namespace DWS_9L { class Program { public static FileInfo[] textsToRead; // Обрабатываемые файлы public static int filesNum = 0; // Кол-во обрабатываемых файлов public static int finishedFilesNum = 0; // Кол-во обработанных файлов public static string[][] readedWords = new string[1185922][]; // Этот массив нужно заполнить public static int[] readedWordsIndexWordsNum = new int[1185922]; // Кол-во элементов в массивах readedWords[x] public static bool[] levelBlocked = new bool[1185922]; public static int Main(string[] args) { DirectoryInfo bookDir = new DirectoryInfo("./texts"); textsToRead = bookDir.GetFiles(); filesNum = textsToRead.Length; for(int i=0; i<1185922; i++){ readedWordsTreeLevelWordsNum[i] = 0; levelBlocked[i] = false; } int pc = Environment.ProcessorCount; Splitter[] splitters = new Splitter[pc]; // Создание собственно "обработчиков" Thread[] splitterThreads = new Thread[pc]; for(int i=0; i<pc; i++){ splitters[i] = new Splitter(); } for(int i=0; i<pc; i++){ splitterThreads[i] = new Thread(new ThreadStart(splitters[i].splitWords)); splitterThreads[i].Priority = ThreadPriority.AboveNormal; } for(int i=0; i<pc; i++){ splitterThreads[i].Start(); } for(int i=0; i<pc; i++){ splitterThreads[i].Join(); } //-- Здесь вывод результатов -- Console.Write("\aPress any key to continue . . . "); Console.ReadKey(true); return 0; } } }
|
Класс Splitter.cs - собственно обработчик:
| Код | using System; using System.IO; using System.Threading;
namespace DWS_9L { public class Splitter { public Splitter() { } public void splitWords(){ while(Program.finishedFilesNum < Program.filesNum){ // Узнаём есть ли еще необработанные файлы int localFileNum = Program.finishedFilesNum; // Запоминаем номер файла с которым работает поток Program.finishedFilesNum++; // Сообщаем остальным потокам, что файл занят //-- Здесь код, который получает из файла массив слов string outWords[] -- for(int z=0; z < outWords.Length; z++){ // Перебираем слова //-- Здесь код, определяющий int sum - первый индекс массива в который нужно добавить слово bool done = false; while(!done){ if(!Program.levelBlocked[sum]){ // Если другие потоки не работают в данный момент с индексом массива [sum] Program.levelBlocked[sum] = true; // Сообщаем остальным потокам, что этот индекс занят if(Program.readedWordsIndexWordsNum[sum] != 0){ // Если в массиве Program.readedWords[sum] есть хоть один элемент bool flag = false; // Флаг, обозначающий - уже добавлено слово в массив или ещё нет for(int y=0; y<Program.readedWordsIndexWordsNum[sum]; y++){ // Ищем слово outWords[z] в массиве Program.readedWords[sum] if(Program.readedWords[sum][y] == outWords[z]){ flag = true; // Если нашли break; } } if(!flag){ // Если слово не найдено - добавляем string[] tmpString = new string[Program.readedWordsIndexWordsNum[sum]]; tmpString = Program.readedWords[sum]; Program.readedWords[sum] = new string[Program.readedWordsIndexWordsNum[sum] + 1]; tmpString.CopyTo(Program.readedWords[sum], 0); Program.readedWords[sum][Program.readedWordsIndexWordsNum[sum]] = outWords[z]; // Строка с ошибкой (индекс находился вне границ массива) Program.readedWordsIndexWordsNum[sum]++; } } else{ // Если в массиве Program.readedWords[sum] нет элементов Program.readedWords[sum] = new string[1]; Program.readedWords[sum][0] = outWords[z]; Program.readedWordsIndexWordsNum[sum]++; } Program.levelBlocked[sum] = false; // Позволяем остальным потокам работать с этим индеском done = true; } } } } } } }
|
|