完成第一个过程后如何运行第二个过程

问题描述 投票:0回答:2

我每隔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是一半数据,几乎每个文件都会发生这种情况。

所以我认为这个问题是由于第二个进程(创建文件)而发生的。那么我应该申请什么解决方案来解决这个问题呢?

c# multithreading linq task filestream
2个回答
0
投票

@Ankit,您删除了代码示例,其中包含与您的问题无关的详细信息,使得回答问题变得更加困难。如果我理解正确的话,你的问题是关于数据准确性的损失,这很可能是由于错误的线程处理,但你的代码中有序列化,日志记录和TimeZone复杂化。代码WriteRecordTest(..)用异步装饰,但在其中找不到await。代码包含未提供的数据类型,为了回答您的问题,我们需要猜测...

从代码的角度出发,很难推断,我想建议重构代码如下:

  1. 生成生产者(发布者)和消费者(订阅者)线程(称为pub-sub模式):
  2. 生产者:在自己的生产者线程中逐行读取控制器文件@"D:\TestSymbolsData.txt",并在并发缓冲区中累积行,比如ConcurrentQueue<T>,因为这些行是有序的。
  3. 消费者:一个不同的线程将检索缓冲区中的行,ConcurrentQueue<T>,并将这些行处理为tempWriter。然后每5秒钟将关闭tempWriter并创建/打开一个新的。这个5秒的间隔不需要是并发的,在处理从缓冲区中检索的下一行之前,如果计时器小于5秒,你可以检查一个计时器然后继续消费者的工作。否则,关闭之前的tempWriter并创建一个新的并继续BAU(照常营业)。
  4. 您需要注意一个空缓冲区并让消费者不会崩溃但是等待。当消费者更快地处理缓冲区中的数据然后生产者将数据生成到缓冲区中时,就会发生这种情况。
  5. 你必须注意一个完整的缓冲区,生产者需要等待而不是崩溃。当生产者生成数据的速度快于消费者从缓冲区处理数据时,就会发生这种情况。
  6. 您需要有一个触发器来发出信号并结束进程。

0
投票

我认为,使用tempwriter对象作为锁定对象是一个坏主意...

但是,更重要的是,你只能在WriteRecordTest锁定你的tempwriter,所以锁在createtextfile没用。

我想,只要你在自己的代码片段中,或者甚至在同一个类中,你应该能够使用一个简单的布尔变量来锁定对文件资源的访问

  • 检查布尔值是否为假,如果不做则
  • 然后将布尔值设置为true并执行您的工作(一方面,写入文件,另一方面刷新文件并重新打开下一个文件)

有了这些提示,应该可以解决你的问题......

[编辑于2019-03-11:]

起初我想,很容易为您的代码提供更正。但是再看看,我看不到你想要达到的目标。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.