Share via


How to have your timer1 pause for 20 seconds then carry on c#

Question

Thursday, April 12, 2018 10:15 AM

Hi, I am reading through a directory every 30 seconds and reading any files that are in this directory.

So on timer1_Tick, I foreach through a directory using DirectoryInfo, the timer is set to thirty seconds, after it has processed the first file I would like it to pause for 20 seconds before reading the next file. How can I do this? 

Here is my code:

private void timer1_Tick( object sender , EventArgs e )
{
   DirectoryInfo    dirInfo     = new DirectoryInfo ( 
   _dirName );
   
   foreach ( var Filein dirInfo.GetFiles ( ) )
    {
          if ( pFileLength > 0 )
      {
        using ( var stream = pFile.OpenRead ( ) )
        {
        using ( var reader = new StreamReader ( 
                stream ) )
        {
        string line;
        while ( ( line = reader.ReadLine ( ) ) != 
                null )
        {
        
        if ( line.Contains("Director")( line ) )                       
                wantedData.Add ( line );
        }
         }
       }
    }

 

At the end of the foreach I would like to pause for 20 seconds, do I add another timer? if so how and where or can I pause the timer1 for 20 seconds then loop through the next file?

Thanks for your help.

CuriousCoder

All replies (7)

Thursday, April 12, 2018 2:09 PM ✅Answered | 1 vote

UPDATE: Reread your question and realized you wanted to pause between file reads instead of the polling process. Please clarify why you would read the directory and then pause between each file read (since the directory contents could change during the 20 second interval).

Why are you polling a directory structure? Have you considered looking at using FileSystemWatcher which eliminates the need for polling and is going to be more efficient in terms of resources needed?

When working with timers be sure to clarify which one you're using. The core library has 2 timer classes, each UI framework adds another timer.

System.Threading.Timer

System.Timers.Timer

System.Windows.Forms.Timer

Since you are receiving an EventArgs argument it appears you're using the Windows Forms version. It is critically important to note that because you're using this version that the event is occurring on the UI thread. Therefore any work you do on this thread will stall the UI. Don't make blocking calls here otherwise your UI will stall.

To pause a timer you just stop or disable it (depending upon the timer you're using). start it again when you're done. 20 seconds doesn't indicate whether that is after you've done your polling or not. Here's how I'd do it (if I weren't using FileSystemWatcher) on a Winforms timer.

//When setting up your timer set the interval to the delay you want
timer1.Interval = 20000; //20 seconds

//In tick handler
timer1.Stop();

//Do your work

//Start the timer over again
timer1.Start();

Michael Taylor http://www.michaeltaylorp3.net


Friday, April 13, 2018 5:57 AM ✅Answered | 1 vote

Hello CuriousCoder15,

Or you use async/await keyword to set 20s seconds without blocking UI thread. Simple code like below.

        private async void button1_Click(object sender, EventArgs e)
        {
            string _dirName = @"D:\Test";

            DirectoryInfo dirInfo = new DirectoryInfo(_dirName);

            foreach (var File in dirInfo.GetFiles())
            {
                ...
                //when file finish operating, run the below code will pause 20s without blocking
                await Task.Delay(20000);           
            }
        }

Best Regards,

Neil Hu

MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact [email protected].


Thursday, April 12, 2018 10:41 AM | 1 vote

Hi!

In my opinion having a two timers is good solution. You also can create an enumeration for describe a current state or use a boolean value and use only one timer, but it will be little bit overcomplicated. I would like to suggest you use a Queue to store FileInfo for the Tick handlers.

  public partial class Form1 : Form
  {

    private Timer directoryTimer = new Timer();
    private Timer fileTimer = new Timer();
    private string _dirName = @"d:\MyDirectory";
    private Queue<FileInfo> files = new Queue<FileInfo>();

    public Form1()
    {
      fileTimer.Interval = 20_000;
      fileTimer.Tick += FileTimer_Tick;

      directoryTimer.Interval = 30_000;
      directoryTimer.Tick += DirectoryTimer_Tick;

      directoryTimer.Start();
    }

    private void FileTimer_Tick(object sender, EventArgs e) {

      if (files.Count == 0) {
        fileTimer.Stop();
        directoryTimer.Start();        return;
      }

      var file = files.Dequeue();

      // do something with file info
    }

    private void DirectoryTimer_Tick(object sender, EventArgs e) {

      DirectoryInfo dirInfo = new DirectoryInfo(_dirName);

      // collect all files to the temporary structure
      foreach (var file in dirInfo.GetFiles())
        files.Enqueue(file);

      directoryTimer.Stop();
      fileTimer.Start();
    }
  }

Thursday, April 12, 2018 12:47 PM

Hi, thanks, I'm just trying to understand how it works and how to use it in my program. I will let you know when I finish.

Thanks

CuriousCoder


Friday, April 13, 2018 7:45 AM

Thank you for your comments, I am just learning to program so wasn't aware there were so many timer classes, noted for next time.

I am polling a directory because I want to take the info from the files that arrive there and upload them to the database if more than one file arrives in the folder at the same time then the process slows and I was worried about occupying my DB for too long so I wanted to ensure that there would be a break after reading each file. All file names once read are also added to my DB, when I loop through the folder again I check with my DB to see if I have already looked at the file in the folder, if not then process it. So I never miss a file but as far as I know with the fileWatcher class it is possible to miss a file if more than one file arrives at the same time. I may be wrong but I am learning. Hope that provides a little more context.

Thanks again 

CuriousCoder


Friday, April 13, 2018 1:48 PM | 1 vote

" if more than one file arrives in the folder at the same time then the process slows and I was worried about occupying my DB for too long"

Databases can handle 100s or 1000s of transactions a second, depending on the DB, server, etc. You aren't going to slow down your DB unless you're doing something crazy like running queries that take seconds to run. Don't put arbitrary slowdowns in your code for that.

"but as far as I know with the fileWatcher class it is possible to miss a file"

FSW isn't going to miss file updates except for in extreme error cases. It is actually going to be far more accurate than your code. Your code won't detect new files for a long time compared to FSW which will notify you immediately. 

The reason people run into issues with the FSW is that they write code that takes too long to execute and the notification buffer fills up. FSW is called from the file system directly via the Journaling API. Since this is happening as IO is occurring it has to be fast. The correct solution for working with FSW is to add the notification information to a queue and then have a background process do the actual heavy lifting. You'll never miss a notification at that point. Note however that you can (and will) get multiple events for the same file so you need to handle that. But you're already going to have that situation with your existing code anyway.

There are many good articles on how to use FSW properly. Here's one I wrote years ago. It is old but the code is still the same. I would use this over a timer always. There is no real reason for a timer in this type of situation.

Michael Taylor http://www.michaeltaylorp3.net


Monday, April 16, 2018 8:45 AM

I will read through your article and practice with the watcher class, thank you for the link.

Kind Regards

 

CuriousCoder