Как запустить второй процесс после завершения первого процесса - PullRequest
0 голосов
/ 08 марта 2019

Я генерирую новый текстовый файл каждые 5 секунд и записываю в него записи.У меня есть разные методы для обоих процессов.Поэтому, прежде всего, он создает файл и запускает процесс для записи в него данных, и снова, если создать метод доступа к файлу снова через 5 секунд, то запись не будет полностью записана в предыдущем файле.Итак, как я могу завершить его и после этого создать новый файл?

Я применяю приведенный ниже код для реализации:

const string filePath = @"D:\TestSymbolsData.txt";
public static void ReadAndWriteInFile()
{
     Timer timer = new .Timer(new TimerCallback(createtxtFile));
     timer.Change(0L, 5000);

     File.ReadLines(filePath).ToList().Take(1000)
                .AsParallel()
                .Select(JsonConvert.DeserializeObject<List<LiveAMData>>)
                .ForAll(WriteRecordTest);
}

static StreamWriter tempWriter;
static System.Threading.Tasks.Task t1;
public static async void WriteRecordTest(List<LiveAMData> data)
{
     List<LiveAMData> data1 = data.AsParallel().Where(x => symbolList.Contains(x.sym)).ToList();
     foreach (var dt in data1)
     {
          t1 = Task.Run(() =>
          {
              var result = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc).AddTicks(((long)dt.s) * TimeSpan.TicksPerMillisecond);
              DateTime newDT = TimeZoneInfo.ConvertTimeFromUtc(result, targetZone);
              lock(tempWriter)
              {
                  tempWriter.WriteLine(dt.sym + ", " + newDT.ToString("dd/MM/yyyy HH:mm:ss fff tt") + ", " + dt.v);
              }
          });
     }
}

public static void createtxtFile(object state)
{
    if(t1 != null)
    {
        Task.WhenAll(t1);
        sLogFname = $@"D:\LogFiles\{DateTime.Now:yyyyMMdd_HHmmss}.txt";
        tempWriter = new StreamWriter(new FileStream(sLogFname, FileMode.Append, FileAccess.Write));
    }
    else
    {
        sLogFname = $@"D:\LogFiles\{DateTime.Now:yyyyMMdd_HHmmss}.txt";
        tempWriter = new StreamWriter(new FileStream(sLogFname, FileMode.Append, FileAccess.Write));
    }
}

, и в файлах последняя строка становится похожей на остановку в середине процесса исоздать новый файл.

CORE, 05/02/2019 10:27:00 000 AM, 548
YUM, 05/02/2019 10:27:00 000 AM, 1109
DVY, 05/02/2019 10:27

На самом деле последняя запись DVY - это половина данных, и это происходит почти во всех файлах.

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

Ответы [ 2 ]

0 голосов
/ 10 марта 2019

@ Ankit, вы оставили свой код с деталями, которые не имеют отношения к вашему вопросу, что затрудняет ответ на ваш вопрос.Ваш вопрос, если я правильно понимаю, касается потери точности данных, что более вероятно из-за неправильной обработки потоков, но в вашем коде есть сериализация, ведение журнала и усложнение TimeZone.Код WriteRecordTest (..) украшен асинхронными сообщениями, но в нем не может быть никаких ожиданий.Код содержит типы данных, которые не предоставлены, и чтобы ответить на ваш вопрос, нам нужно угадать ...

Исходя из того, что код, как есть, трудно рассуждать, яхотел бы предложить реструктуризацию кода следующим образом:

  1. Создание потоков производителя (издателя) и потребителя (подписчика) (известных как шаблон pub-sub):
  2. Производитель:читать файл контроллера, @"D:\TestSymbolsData.txt", построчно, в его собственном потоке производителя и накапливать строки в параллельном буфере, скажем, ConcurrentQueue<T>, потому что эти строки упорядочены.
  3. Потребитель: другой потокизвлечет строки из буфера, ConcurrentQueue<T>, и обработает строки в tempWriter.Затем каждые 5 секунд tempWriter будет закрыт, и будет создан / открыт новый.Этот 5-секундный интервал не обязательно должен быть параллельным, перед обработкой следующей строки, извлеченной из буфера, вы можете проверить таймер, если таймер меньше 5 секунд, а затем продолжить работу с потребителем.В противном случае закройте предыдущий tempWriter, создайте новый и продолжите работу с BAU (как обычно).
  4. Вам нужно будет помнить о пустом буфере и заставлять потребителя не падать, а ждать.Это произойдет, когда потребитель обрабатывает данные в буфере быстрее, чем производитель создает данные в буфере.
  5. Вам нужно будет помнить о полном буфере, и производителю нужно будет скорее дождаться, чем завершиться сбоем.Это произойдет, когда производитель генерирует данные быстрее, чем потребитель обрабатывает их из буфера.
  6. Вам понадобится триггер для сигнализации и завершения процессов.
0 голосов
/ 08 марта 2019

Я думаю, это плохая идея использовать объект темпрайтера в качестве объекта блокировки ...

Но, что более важно, вы блокируете свой темпрайер только в WriteRecordTest, поэтому блокировка не имеетиспользовать в createtextfile.

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

  • проверить, является ли логическое значение ложным, если нет, ничего не делать
  • , затем установить логическое значение на true и выполнять свою работу (с одной стороны, записать в файл идругой рукой очистите файл и снова откройте следующий)

С помощью этих советов вы сможете решить вашу проблему ...

[Редактировать в 2019-03-11:]

Сначала я подумал, что было бы легко предоставить вам исправления к вашему коду.Но при втором взгляде я не вижу, чего ты хочешь достичь.

...