c# - Background operation and blocking main form -
here scenario: on form have list of direcotories, button , control display multiline text. in loop try find files in each directory , delete them. when file deleted want add text multiline control. problem when text added can not else. form blocked , if try do anytching stops responding. files deleted using backgroundworker
private void backgroundworker1_dowork(object sender, doworkeventargs e) { //this datatable directories , other info maindataset.czyszczeniedatatable czyszczenie = e.argument maindataset.czyszczeniedatatable; czyscpliki(czyszczenie, reportprogress); } private void czyscpliki(maindataset.czyszczeniedatatable czyszczenie, reportprogressdel del) { directoryinfo dir = null; fileinfo[] files = null; bool subfolder = false; string katalog = ""; string maska = ""; string[] maski = null; long total=0; string dirs; string files; long filelen; //foreach directory delete foreach (datarow r in czyszczenie.rows) { //canread - check if row not deleted or detached //r["czysc"].asbool() - check if directory should cleared if (r.canread() && r["czysc"].asbool()) { subfolder = r["podkatalogi"].asbool(); katalog = r["katalog"].asstring().trimend('\\'); maska = r["maska"].asstring(); if (maska.isempty()) maska = "*"; maski = maska.split(';'); dir = new directoryinfo(katalog); if (dir.exists) { foreach (string s in maski) { files = dir.getfiles(s, (subfolder ? searchoption.alldirectories : searchoption.topdirectoryonly)); dir.getfiles(); foreach (fileinfo f in files) { dirs = f.directory.fullname; files = f.name; filelen = f.length; try { f.delete(); total += filelen; if (del != null) //here problem: del - delegate report state //when called blocks form del(dirs, files, filelen, total); } catch (exception ex) { } } } } } } } //this delegate appends text in multiline control //memoedit1 control //cereportprogress.checked - check if report should added private void reportprogress(string directory, string file, long size, long totalsize) { if (memoedit1.invokerequired) { memoedit1.begininvoke(new action<string, string, long, long>(reportprogress), directory, file, size, totalsize); } else { if (cereportprogress.checked) { if (file.isempty()) memoedit1.appendtext("\r\nczyszczenie katalogu " + directory); else { memoedit1.appendtext(file); if (size > 0) { if (size > 1048576) { decimal d = size / 1048576; d = decimal.round(d, 2); memoedit1.appendtext("\twielkość : " + d.asstring() + " megabajtów", false); } else if (size > 1024) { decimal d = (decimal)size / (decimal)1024; d = decimal.round(d, 2); memoedit1.appendtext("\twielkość : " + d.asstring() + " kilobajtów", false); } else memoedit1.appendtext("\twielkość : " + size.asstring() + " bajtów", false); } if (totalsize > 0) { if (totalsize > 1073741824) { decimal d = (decimal)totalsize / (decimal)1073741824; d = decimal.round(d, 2); memoedit1.appendtext("zwolniono dotychczas : " + d.asstring() + " gigabajtów"); } else if (totalsize > 1048576) { decimal d = (decimal)totalsize / (decimal)1048576; d = decimal.round(d, 2); memoedit1.appendtext("zwolniono dotychczas : " + d.asstring() + " megabajtów"); } else if (totalsize > 1024) { decimal d = (decimal)totalsize / (decimal)1024; d = decimal.round(d, 2); memoedit1.appendtext("zwolniono dotychczas : " + d.asstring() + " kilobajtów"); } else memoedit1.appendtext("zwolniono dotychczas : " + totalsize.asstring() + " bajtów"); } } //scroll end of control memoedit1.scrolltoend(); } } }
how can improve make not blocking form?
you calling reportprogress often. more 1000 times per second , ui thread gets flooded requests cannot keep with. won't around doing normal duties, include painting controls , responding mouse , keyboard. looks frozen. gets worse when ui update code gets more expensive, updating text in textbox when there's lot of text in can quite slow.
the diagnostic still seeing ui frozen while after bgw stops running, working on emptying backlog in invoke request queue, jumping alive when queue emptied.
you need throttle rate @ call begininvoke(). never makes more sense call more once every 50 milliseconds, human cannot perceive difference beyond that. collect info in list<> can begininvoke() lot less frequently. that's still no complete guarantee if worker can produce results faster ui thread ever keep with. in case slowing down worker fix. easy using invoke instead of begininvoke.
Comments
Post a Comment