Синхронизация списков, привязка списка к файлу

Energizer

Client
Регистрация
19.06.2013
Сообщения
36
Благодарностей
4
Баллы
8
Всем привет.

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

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 714
Баллы
113
Логикой. Что-то указываете в настройках и в начале проекта читая значение переменной из настроек логикой строите две ветки
 

Energizer

Client
Регистрация
19.06.2013
Сообщения
36
Благодарностей
4
Баллы
8
Ну понятно что логикой. Я говорил о реализации моего алгоритма. Конкретно как из кода C# в первом случае при чтении всех данных из одного файла, привязать этот файл к списку в проекте, чтобы он был на все потоки один. И для второго случая, как распределить чтение из файлов между потоками, при этом ни один файл не должен быть прочитан дважды, после взятия файл должен быть уничтожен, а в случае ошибки (тут уже своя логика отлова этой ошибки), файл должен быть снова записан в ту же папку, после чего его опять сможет прочитать какой-либо из потоков.
 

zortexx

Client
Регистрация
19.09.2011
Сообщения
2 520
Благодарностей
1 225
Баллы
113
Привязать один список на все потоки не получится - список существует только внутри инстанса. Только если не привязан к файлу. Проще резать файл по количеству потоков. Это если я правильно понял суть задачи.
 

Energizer

Client
Регистрация
19.06.2013
Сообщения
36
Благодарностей
4
Баллы
8
Алгоритм такой.

1) Если во входных настройках стоит галочка "Брать из одного файла", то мы привязываем список к файлу и он один на все потоки будет.
2) Если галочка не стоит, то мы берем из указанной папки рандомно файлы и читаем их, например, с помощью System.IO.File.ReadAllLines(). И тут каждому потоку свой файл с уничтожением оного после взятия. В случае ошибки возврат в ту же папку.

Вот как все это провернуть из сниппета C#. Чувствую без всяких lock(SyncObject) и глобальных переменных тут не обойтись. Но не знаю как подступиться хотя бы к этому. Не шарю я в Сях, а еще меньше понимаю внутреннюю работу самого Зенно, там много непоняток.
 

Irbis

Client
Регистрация
02.03.2014
Сообщения
195
Благодарностей
120
Баллы
43
Если у каждого потока свои значения списков и переменных, тогда можно и без глобальных переменных обойтись.
Файлы наверное лучше не уничтожать, а перемещать в другую папку и записывать название файла файла в переменную.
В случае ошибки, можно будет переместить их обратно в папку из которой взяли.
 

Nick

Client
Регистрация
22.07.2014
Сообщения
1 980
Благодарностей
816
Баллы
113
1) По моему нубскому мнению, это сработает только если весь файл считать в какую-то глобальную переменную и с ней из разных потоков работать. Через lock(SyncObject), конечно.
2) Каждый экземпляр проверяет, есть ли для данного файла соответствующий ему файл filename.lck. Если нет, он его создаёт и считает своим, другие экземпляры его тогда не трогают. Если работа не получилась, то .lck файл стирается, и его может кто-то другой опять подобрать и поработать с ним.
 
  • Спасибо
Реакции: zortexx

zortexx

Client
Регистрация
19.09.2011
Сообщения
2 520
Благодарностей
1 225
Баллы
113

Energizer

Client
Регистрация
19.06.2013
Сообщения
36
Благодарностей
4
Баллы
8
Всем спасибо за подсказки. Вот как это вижу я.

Имеем флаг в глобальной переменной о режиме работы. Это чтобы в случае ветки (1) привязать общий список с синхронизацией в файл единожды за всю работу проекта.

Если (1)

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

Если (2)

- считываем флаг в глобальной переменной
- если флаг не установлен, устанавливаем
- в сниппете C# лочим работу потоков на этом участке и считываем все файлы во временный список с помощью Directory.GetFiles()
- если файлов нет - завершаем работу потока
- рандомно выбираем файл из списка
- считываем файл
- удаляем файл
- разлочиваем потоки

(BAD END)

В случаи аварии в самом шаблоне записываем файл обратно. При этом блокируем поток.

Прошу помочь оформить это в код примерно.
 
Последнее редактирование:

Irbis

Client
Регистрация
02.03.2014
Сообщения
195
Благодарностей
120
Баллы
43
По второму попробуйте так, может получиться.
Код:
// Предполагается, что файлы лежат в папке "Списки" в директории проекта.
string dir = project.Directory +"/Списки";
Random ran = new Random();
// Блокируем списки.
lock(SyncObjects.ListSyncer)
{
// Считываем файлы в список "all".
List<string> all = new List<string>(Directory.GetFiles(dir));
// Проверяем количество файлов в папке. Если файлов нет возвращаем 0, в противном случае 1.
    if(all.count != 0)
    {
// Получаем случайный файл.
    string path = all[ran.Next(all.Count)];
// Считываем файл в массив.
    string[] a = File.ReadAllLines(path);
// Удаляем файл.
    File.Delete(path);
// Наполняем список в проекте - "Список 1".
    foreach(var item in a)
    {
        project.Lists["Список 1"].Add(item);
    }
    return 1;
    }
    else{
        return 0;
    }
}
Первые два пункта не совсем понятны. У вас одни и те же действия в обоих случаях.
 
  • Спасибо
Реакции: DenisK и Energizer

Кто просматривает тему: (Всего: 2, Пользователи: 0, Гости: 2)