Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Несколько потоков работают с ошибкой, Ошибка при использовании общих данных 
:(
    Опции темы
Wecoyote
Дата 18.4.2010, 06:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 26.12.2009

Репутация: нет
Всего: нет



Всем привет. Бьюсь над мультипоточностью уже вторые сутки.

Заранее прошу меня извинить, описать проблему без приведения своего запутанного кода не смог.

В коде приведённом ниже открываются текстовые файлы и разделяются на неповторяющиеся слова. (различные слова)

В один поток все выполняется правильно и без ошибок.

Если запускаю столько потоков, сколько ядер процессора - то, при одинаковых исходных данных - в результате разное количество слов, что по определению невозможно. Либо ошибка (индекс вне границ массива).

Если кому-нибудь не лень разобраться в моём коде и указать на ошибку - буду весьма признателен.


Класс 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;
                        }
                    }
                }
            }
        }
    }
}


Это сообщение отредактировал(а) Wecoyote - 18.4.2010, 06:35
PM MAIL   Вверх
Heinzz
Дата 18.4.2010, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 12.12.2008
Где: .net

Репутация: 5
Всего: 9



в Вашем коде не разбирался, но очень похоже на то что не синхронизированно общение с переменной счетчиком или коллекцией. Те к одной переменной без объявления ее временно закрытой нельзя обращаться из разных потоков. Если же Вы все же это делаете, используйте Increment для value type или lock для ссылочных типов.



--------------------
user posted image
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0655 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.