c# - FileWatcher typicall implementation? -


i building app, watching files. pretty fresh in programming (maybe) have little issue, because dont have real practice. program working, dont know how usally implemented in "real" software. please overview , comment. because have possible in datefiles class , less possible in mainviewmodel. yes app in build on mvvm base.

my current state:

  • in mainviewmodel

    public static string configurationfilessourcepath2;

    private void initializefiles() {     // new instance of datefiles     df = new datafiles();      // path datefiles     df.configurationfilessourcepath = configurationfilessourcepath;      // run initialization method establish "filewatching"     df.initializefiles();      // refresh listview in view     refreshfilelist();      // assign handler propertychanged event     df.propertychanged += df_propertychanged; }  // if change inside datefiles private void df_propertychanged(object sender, propertychangedeventargs e) {     refreshfilelist(); }  // refresh file list public void refreshfilelist() {     fileslist = new observablecollection<files>();      foreach (var item in df.fileslist)     {         fileslist.add(item);     }      notifypropertychanged("fileslist"); } 
  • datafiles class:

     public class datafiles : viewmodelbase  { public filesystemwatcher filewatcher; public string configurationfilessourcepath; public observablecollection<files> fileslist { get; set; } = new observablecollection<files>();  public void initializefiles() {     // create new filesystemwatcher     filewatcher = new filesystemwatcher();      // set filter catch xal files     filewatcher.filter = "*.txt";      // set path     filewatcher.path = configurationfilessourcepath;      // subscribe created event     filewatcher.created += new filesystemeventhandler(fileonchanged);     filewatcher.changed += new filesystemeventhandler(fileonchanged);     filewatcher.deleted += new filesystemeventhandler(fileonchanged);     filewatcher.renamed += new renamedeventhandler(fileonrenamed);      // enable filesystemwatcher events     filewatcher.enableraisingevents = true;      refreshfileslist(); }  private void fileonchanged(object sender, filesystemeventargs e) {     refreshfileslist(); }  private void fileonrenamed(object sender, renamedeventargs e) {     refreshfileslist(); }  public void refreshfileslist() {     fileslist.clear();      directoryinfo dir = new directoryinfo(configurationfilessourcepath);      string[] extensions = new[] { ".txt" };      int nof = 0;     foreach (fileinfo file in dir.getfiles().where(f => extensions.contains(f.extension.tolower())).toarray())     {         nof++;          fileslist.add(new files()         {             fileid = nof,             filename = file.name,             filechanged = file.lastwritetime.tostring(),             filecreated = file.creationtime.tostring(),             onlynamewithoutextension = path.getfilenamewithoutextension(file.name)         });         notifypropertychanged("fileslist");     } } 

there several issues code. among important ones - rebuild whole file list on every change (while filesystemeventargs arguments provide info has changed , where) , don't update observablecollection on ui thread. @ following code (but keep in mind sample spot problems):

public class datafiles : idisposable {     public filesystemwatcher filewatcher;     private readonly object filelistlock = new object();     // don't need public setter on     public observablecollection<files> fileslist { get; } = new observablecollection<files>();      // pass path here, no need use property     public void initializefiles(string path) {         // dispose existing watcher, if         disposewatcher();         // create new filesystemwatcher         filewatcher = new filesystemwatcher();         // set filter catch xal files         filewatcher.filter = "*.txt";         // set path         filewatcher.path = path;         // subscribe created event         filewatcher.created += new filesystemeventhandler(fileonchanged);         filewatcher.changed += new filesystemeventhandler(fileonchanged);         filewatcher.deleted += new filesystemeventhandler(fileonchanged);         filewatcher.renamed += new renamedeventhandler(fileonrenamed);         // don't refreshfileslist on ui thread, might take time , block ui         task.run(() => refreshfileslist());         // enable filesystemwatcher events         filewatcher.enableraisingevents = true;     }      private void fileonchanged(object sender, filesystemeventargs e) {         // lock here avoid race conditions refreshfileslist         lock (filelistlock) {             // better use dictionary avoid looping on files             // looping still better rebuilding whole list             var file = fileslist.firstordefault(c => string.equals(c.fullpath, e.fullpath, stringcomparison.ordinalignorecase));             if (file != null) {                 if (e.changetype == watcherchangetypes.deleted)                     ; // delete                 else                     ; // update file properties             }             else {                 // add new, unless event delete             }         }     }      private void fileonrenamed(object sender, renamedeventargs e) {         lock (filelistlock) {             // better use dictionary avoid looping on files             var file = fileslist.firstordefault(c => string.equals(c.fullpath, e.oldfullpath, stringcomparison.ordinalignorecase));             if (file != null) {                 file.fullpath = e.fullpath;             }             else {                 // add new             }         }     }      public void refreshfileslist() {         // need lock here, because there race condition between method , fileonrenamed \ fileonchanged,          // , might lose updates or duplicates.          lock (filelistlock) {             // update observablecollection on ui thread             onuithreaddo(() => {                 fileslist.clear();             });              directoryinfo dir = new directoryinfo(filewatcher.path);             int nof = 0;              var files = new list<files>();             // use enumeratefiles             foreach (fileinfo file in dir.enumeratefiles("*.txt")) {                 nof++;                 int tmp = nof;                 // if working ui (that case if use observablecollection) -                 // need update collection ui thread if have bound controls                                     files.add(new files() {                     fileid = tmp,                     fullpath = file.fullname,                     filechanged = file.lastwritetime,                     filecreated = file.creationtime,                 });                 // don't                 // notifypropertychanged("fileslist");             }              // publish them collection on ui thread             onuithreaddo(() => {                 foreach (var file in files)                     fileslist.add(file);             });         }     }      private void onuithreaddo(action a) {         if (application.current.checkaccess())             a();         else             application.current.dispatcher.begininvoke(a);     }      public void dispose() {         disposewatcher();     }      private void disposewatcher() {         if (filewatcher != null) {             filewatcher.enableraisingevents = false;             filewatcher.created -= fileonchanged;             filewatcher.deleted -= fileonchanged;             filewatcher.changed -= fileonchanged;             filewatcher.renamed -= fileonrenamed;             filewatcher.dispose();         }     } }  public class files : inotifypropertychanged { // implement inotifypropertychanged, because need reflect property changes in ui     public int fileid { get; set; }     public string fullpath { get; set; }     public string filename => path.getfilename(fullpath);     public datetime filechanged { get; set; }     public datetime filecreated { get; set; }     public string onlynamewithoutextension => path.getfilenamewithoutextension(fullpath); } 

Comments

Popular posts from this blog

java - Date formats difference between yyyy-MM-dd'T'HH:mm:ss and yyyy-MM-dd'T'HH:mm:ssXXX -

c# - Get rid of xmlns attribute when adding node to existing xml -