1. Problem Description
ProgramTo monitor file changes in a directory: once a new or old file in the directory is overwritten, the program needs to read and process the file content. So the followingCode:
Public Void Initial ()
{
System. Io. filesystemwatcher FSW = New System. Io. filesystemwatcher ();
FSW. Filter = " *.* " ;
FSW. policyfilter = Policyfilters. filename |
Policyfilters. lastwrite |
Policyfilters. creationtime;
// Add event handlers.
FSW. Created + = New Filesystemeventhandler (fsw_changed );
FSW. Changed + = New Filesystemeventhandler (fsw_changed );
// Begin watching.
FSW. enableraisingevents = True ;
}
Void Fsw_changed ( Object Sender, filesystemeventargs E)
{
MessageBox. Show ("Changed", E. Name );
}
It is found that when a file changes, the change event is repeatedly triggered several times. This may result in repeated processing of the same file.
2. solution:
After a search on Google, get the following information: "... You can refer to the log4net practice. You can use a timer to delay the timer for a period of time in file event processing before loading the new configuration file. This prevents multiple change events from being triggered by an operation on the file, and the configuration file is loaded multiple times. "
The Code of log4net-xmlconfigurator. CS is studied, and the code is modified as follows by referring to log4net:
The basic idea is to use the timer, start the timer when the event is triggered, and write down the file name. When the timer arrives, the file is actually processed.
(1). Define Variables
Private Int Timeoutmillis = 2000 ; // Timer trigger Interval
System. Io. filesystemwatcher FSW = New System. Io. filesystemwatcher ();
System. Threading. Timer m_timer = Null ;
List < String > Files = New List < String > (); // Record the queue of files to be processed
(2) initialize filesystemwatcher and Timer
FSW. Filter = " *.* " ;
FSW. policyfilter = Policyfilters. filename |
Policyfilters. lastwrite |
Policyfilters. creationtime;
// Add event handlers.
FSW. Created + = New Filesystemeventhandler (fsw_changed );
FSW. Changed + = New Filesystemeventhandler (fsw_changed );
// Begin watching.
FSW. enableraisingevents = True ;
// Create the timer that will be used to deliver events. Set as Disabled
If (M_timer = Null )
{
// Set the timer callback function. The timer is not started.
M_timer = New System. Threading. Timer ( New Timercallback (onwatchedfilechange ),
Null , Timeout. Infinite, timeout. Infinite );
}
(3) file monitoring event trigger code: Modify the timer, record the file name to be processed later
Void Fsw_changed ( Object Sender, filesystemeventargs E)
{
Mutex = New Mutex ( False , " FSW " );
Mutex. waitone ();
If ( ! Files. Contains (E. Name ))
{
Files. Add (E. Name );
}
Mutex. releasemutex ();
// Reset the trigger interval of the timer and trigger it only once.
M_timer.change (timeoutmillis, timeout. Infinite );
}
(4). timer event trigger code: actual File Processing
Private Void Onwatchedfilechange ( Object State)
{
List < String > Backup = New List < String > ();
Mutex = New Mutex ( False , " FSW " );
Mutex. waitone ();
Backup. addrange (files );
Files. Clear ();
Mutex. releasemutex ();
Foreach ( String File In Backup)
{
MessageBox. Show ("File Change", File+ "Changed");
}
}
Attached to me is not filesystemwatcher, but it is also a solution to the problem of delegate execution events:
Private int timeoutmillis = 1000; // timer trigger Interval
System. Threading. Timer m_timer = NULL;
Public void form1 {
Initializecomponent ();
Lv_common.mousedown + = new mouseeventhandler (this. lv_common_mousedown );
If (m_timer = NULL)
{
M_timer = new system. Threading. Timer (New timercallback (onmdbclick), null, timeout. Infinite, timeout. Infinite );
}
}
/// <Summary>
/// Double-click a listview item to perform the add operation
/// </Summary>
/// <Param name = "sender"> </param>
/// <Param name = "E"> </param>
Private void lv_common_mousedown (Object sender, mouseeventargs E)
{
Listviewitem lvt = lv_common.getitemat (E. X, E. y );
If (lvt! = NULL)
{
If (E. Button = mousebuttons. Left & E. clicks = 2)
{
M_timer.change (timeoutmillis, timeout. Infinite );
}
}
}
/// <Summary>
/// The event that is executed after double-clicking
/// </Summary>
/// <Param name = "state"> </param>
Private void onmdbclick (object state)
{
MessageBox. Show ("click ");
}
Hope to help you!