我每隔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是一半数据,几乎每个文件都会发生这种情况。
所以我认为这个问题是由于第二个进程(创建文件)而发生的。那么我应该申请什么解决方案来解决这个问题呢?
@Ankit,您删除了代码示例,其中包含与您的问题无关的详细信息,使得回答问题变得更加困难。如果我理解正确的话,你的问题是关于数据准确性的损失,这很可能是由于错误的线程处理,但你的代码中有序列化,日志记录和TimeZone复杂化。代码WriteRecordTest(..)用异步装饰,但在其中找不到await。代码包含未提供的数据类型,为了回答您的问题,我们需要猜测...
从代码的角度出发,很难推断,我想建议重构代码如下:
@"D:\TestSymbolsData.txt"
,并在并发缓冲区中累积行,比如ConcurrentQueue<T>
,因为这些行是有序的。ConcurrentQueue<T>
,并将这些行处理为tempWriter
。然后每5秒钟将关闭tempWriter
并创建/打开一个新的。这个5秒的间隔不需要是并发的,在处理从缓冲区中检索的下一行之前,如果计时器小于5秒,你可以检查一个计时器然后继续消费者的工作。否则,关闭之前的tempWriter
并创建一个新的并继续BAU(照常营业)。我认为,使用tempwriter对象作为锁定对象是一个坏主意...
但是,更重要的是,你只能在WriteRecordTest
锁定你的tempwriter,所以锁在createtextfile
没用。
我想,只要你在自己的代码片段中,或者甚至在同一个类中,你应该能够使用一个简单的布尔变量来锁定对文件资源的访问
有了这些提示,应该可以解决你的问题......
[编辑于2019-03-11:]
起初我想,很容易为您的代码提供更正。但是再看看,我看不到你想要达到的目标。