c# - How to know when all my Producer - Consumer jobs have finished -
i have winforms
application read several network folders , search files inside folders, function receive list<stirng> folders
:
private decimal _numberoffiles; private static list<string> _folders; public delegate void onfileadddelegate(list<string> files); public event onfileadddelegate onfileaddeventhandler; public delegate void onfinishsearchdelegate(); public event onfinishsearchdelegate onfinishsearcheventhandler; public void searchfiles() { foreach (string folder in _folders) { if (directory.exists(folder)) { var files = directory.enumeratefiles(folder, "*.doc", searchoption.topdirectoryonly) .orderbydescending(x => new fileinfo(x).creationtime).take((int)_numberoffiles).tolist<string>(); if (onfileaddeventhandler != null) onfileaddeventhandler(files); } } if (onfinishsearcheventhandler != null) onfinishsearcheventhandler(); }
after onfileaddeventhandler(files)
event fired producerconsumer
class start check list
of files found , work (if file ok fired event main ui add files listview
):
public class producerconsumer { public delegate void onfileadddelegate(pcapfiledetails pcapfiledetails); public event onfileadddelegate onfileaddeventhandler; public delegate void allfilesprocesseddelegate(); public event allfilesprocesseddelegate allfilesprocessedeventhandler; private readonly queue<string> _queue; private int counter; public producerconsumer(int workercount, ienumerable<string> list) { _issearchfinished = true; _queue = new queue<string>(list); // fill queue counter = _queue.count; // set counter (int = 0; < workercount; i++) task.factory.startnew(consumer); } private void consumer() { filechecker filechecker = new filechecker(); (; ; ) { string file; lock (_queue) { // synchronize on queue if (_queue.count == 0) return; // done file = _queue.dequeue(); // file name process } // release lock allow other consumers access queue // job string result = filechecker.check(file); // check file if (onfileaddeventhandler != null && result ) // in case file ok, fired event main ui onfileaddeventhandler(file); // decrement counter if (interlocked.decrement(ref counter) != 0) continue; // not last // done - last if (allfilesprocessedeventhandler != null) allfilesprocessedeventhandler(); return; } } }
now while search in process ui locked prevent unnecessary clicks , want know when folders finish search unlock. problem because search several folders event allfilesprocessedeventhandler()
fired several times , want know when searches finished.
here recursive sample quickio.net
using system; using system.collections.concurrent; using system.threading; using system.threading.tasks; using schwabencode.quickio; namespace consoleapplication3 { internal class program { private static readonly blockingcollection<quickiofileinfo> fileinfos = new blockingcollection<quickiofileinfo>(); private static void main(string[] args) { var task = task.factory.startnew(() => { int32 totalsize = 0; parallel.foreach(fileinfos.getconsumingenumerable(), fi => { interlocked.add(ref totalsize, (int)fi.bytes); }); console.writeline("all docs bytes amount {0}", totalsize); }); processdirectory("c:\\"); fileinfos.completeadding(); task.waitall(task); } private static void processdirectory(string path) { parallel.foreach(quickiodirectory.enumeratedirectories(path), dir => { try { parallel.foreach(quickiodirectory.enumeratefiles(dir), file => { if (file.asfileinfo().extension.equals(".docx")) fileinfos.add(file); }); processdirectory(dir.fullname); } catch (exception e) { console.writeline("unable access directory {0}", dir.fullname); } }); } } }
blocking collection automatically signal parallel foreach when elements have been added, calling completeadding().
to scan 256gb ssd, 74gb left , total of 738k+ files took 16.8s.
Comments
Post a Comment