最近在学习研究多线程,还有异步编程方面的知识,结合自己做的项目,遇到这样一个问题:
写了一个程序,它是个控制台程序,会一直运行直到程序关闭,我想用线程实现的方法是通过一个线程每过五分钟或者一分钟,将这一段时间控制台上显示的内容写入txt里面,保存下来,但是写入的时候,控制台程序还在运行,到下一个一分钟后,在将第二个一分钟的内容写入txt里面保存下来。
大概过程是这样:比如在控制台程序他会一直输入1,2,3,4,5,,,,,N,一分钟后,比如写到60,这时候就将1到60写入到txt文件中,不能影响程序的运行,等第二个一分钟过后,比如写到120,就将61到120写入txt文件中,一直延续下去
这个应该如何实现,我个人认为要用两个线程交替工作,一开始线程1工作,一直监视程序运行,一分钟后线程1将数据写入文本文件,这时候线程2开始监视程序运行,一分钟后将数据写入文本,不然我觉得一个线程写会漏掉数据。
大家觉得可行吗,有实现的代码就更好了。之前一直没接触过多线程编程问题,有点无处下手的感觉。
用一个变量专门标记已经写入的数据,比如产生数据线程产生了0-60的数据,那另以个写入线程开始工作,把60保存为标记变量,下一次开始写入的时候就从61开始。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleLab { class Program { static void Main(string[] args) { Thread p = new Thread(Print); p.Start(); m_Timer = new System.Timers.Timer(5000); m_Timer.Elapsed += m_Timer_Elapsed; m_Timer.Start(); Console.ReadKey(); } static void m_Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { Write(); } private static int m_StartIndex = 0; private static int m_MaxIndex; private static System.Timers.Timer m_Timer; public static void Print() { int max = 100; for (int i = 0; i < max; i++) { Console.WriteLine(i); m_MaxIndex = i; Thread.Sleep(1000); } } public static void Write() { int max = m_MaxIndex; //调用写入操作函数 string message = String.Format("写入{0}-{1}", m_StartIndex, max); m_StartIndex = max + 1; Console.WriteLine(message); } } }
@Firen: 很感谢,这个方法不错,但是实际操作中,我要输出的数据量很大,很多字符,数据是未知的,运行到1分钟的时候,我也不知道会是什么类型数据,不好做标记啊
@halia: 无论输出多少,你总能知道输出了多少,你要保存,肯定知道保存了多少,如果无法标记,你又怎么能知道有没有漏保存呢?
你的问题类似流水线的问题。无需控制线程交替这样麻烦……
1、主线程进行监控,响应输入。(下面缓存到一个列表的操作也可直接在此完成,即输入就加入到列表)
2、开启一个定时器(System.Threading.Timer),定时为1分钟,进行保存数据就好了。或则你觉得可能耗的时间会超过定时的1分钟,那么你可以在这个定时器里面只做少量工作,比如将所有数据缓存到一个列表中,当然这时你需要另一个保存数据的定时器,这个定时器就只负责从列表中获取数据进行保存。为了提高可扩展性你还可以将数据都缓存到一个支持并发的集合中(比如:System.Collections.Concurrent.ConcurrentQueue<String>),对于保存数据的定时器使用Parallel.ForEach()循环该集合去执行
这不是什么两个线程交替工作,你的意思就是简单的"定期把日志输出到文件"这个功能呗,
写一个静态的字符串变量,用来存储日志(即你说的1-60,或是61-120)
写一个日志输出方法,每隔1分钟执行一次,利用Timer,每当输出完成后,直接清空静态变量
感觉没必要你说的这么麻烦,你直接每次输出日志都输出到文件不就可以了,?
用你这个方法,如果运行了1.5分钟的话,还是会丢失半分钟的数据的