Task with Timer crashing a program
I've a little program, that parses all the log files created by another program, and locked by it ( so, no way I can edit or delete those files) . The program runs just fine, and I do it starting a new Task every 10 seconds:
System.Timers.Timer aTimer = new System.Timers.Timer();
public Form1()
{
InitializeComponent();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aT开发者_开发技巧imer.Interval = 10000;
aTimer.Start();
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
var t = Task<int>.Factory.StartNew(() => convert());
}
the only problem arises when there are too many log files : if a new Task is started before the end of the previous one, the program crashes. So, any idea on how to solve this behaviour, or better solutions to the problem?
You could use the lock() statement to lock on an object variable. On the other hand, you might run into thread deadlocks if the parsing of the log files consistently takes longer than the timer interval.
In your OnTimedEvent() function, I would check a boolean member variable that skips the parsing if you are already performing a parse. For example:
public class MyTimerClass
{
private bool isParsing;
// Other methods here which initiate the log file parsing.
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
if (!isParsing)
{
isParsing = true;
ParseLogFiles();
isParsing = false;
}
}
}
The simple solution would be to wait until the previous task is completed.
Write an event that sends a callback when the file is done being parsed.
This is the best I can do with the code provided.
Have you tried to use lock statement inside OnTimeEvent
?
http://msdn.microsoft.com/en-us/library/c5kehkcz(v=VS.100).aspx
You could create a static boolean variable called IsRunning and set it to true when you are moving the logs, before you start moving the logs just check if IsRunning is set to true.
private static bool IsRunning = false;
public void MoveLogs()
{
if (!IsRunning)
{
IsRunning = true;
//Copy log files
IsRunning = false;
}
}
In the current accepted answer there is still the possibility of a race condition in a multi-threaded situation. However unlikely in your case because of the interval, another more threading appropriate solution is to use Monitor.TryEnter
public class MyTimerClass
{
private object _syncObject = new object();
// Other methods here which initiate the log file parsing.
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
if (Monitor.TryEnter(_syncObject) )
{
try
{
ParseLogFiles();
}
finally
{
Monitor.Exit(_syncObject);
}
}
}
}
I believe this is cleaner and gets you in the habit of using the proper thread synchronization mechanism in the framework.
精彩评论