c# - Asynchronous task for image resize -
this image resizer class:
using system; using system.drawing; using system.drawing.imaging; using system.drawing.drawing2d; using system.io; using system.threading.tasks; public class imageresize { private static imagecodecinfo jpgencoder; public async static void resizeimage(string infile, string outfile, double maxdimension, long level) { byte[] buffer; using (stream stream = new filestream(infile, filemode.open)) { buffer = new byte[stream.length]; await task<int>.factory.fromasync(stream.beginread, stream.endread, buffer, 0, buffer.length, null); } using (memorystream memstream = new memorystream(buffer)) { using (image inimage = image.fromstream(memstream)) { double width; double height; if (inimage.height < inimage.width) { width = maxdimension; height = (maxdimension / (double)inimage.width) * inimage.height; } else { height = maxdimension; width = (maxdimension / (double)inimage.height) * inimage.width; } using (bitmap bitmap = new bitmap((int)width, (int)height)) { using (graphics graphics = graphics.fromimage(bitmap)) { graphics.smoothingmode = smoothingmode.highquality; graphics.interpolationmode = interpolationmode.highqualitybicubic; graphics.drawimage(inimage, 0, 0, bitmap.width, bitmap.height); if (inimage.rawformat.guid == imageformat.jpeg.guid) { if (jpgencoder == null) { imagecodecinfo[] ici = imagecodecinfo.getimagedecoders(); foreach (imagecodecinfo info in ici) { if (info.formatid == imageformat.jpeg.guid) { jpgencoder = info; break; } } } if (jpgencoder != null) { encoderparameters ep = new encoderparameters(1); ep.param[0] = new encoderparameter(encoder.quality, level); bitmap.save(outfile, jpgencoder, ep); } else bitmap.save(outfile, inimage.rawformat); } else { // // fill white transparent gifs // graphics.fillrectangle(brushes.white, 0, 0, bitmap.width, bitmap.height); bitmap.save(outfile, inimage.rawformat); } } } } } } }
and register button server click:
httppostedfile file = request.files["ctl00$cph$postfile"]; string filename = ""; if (file.contentlength > 0) { string[] validext = { ".jpg", ".jpeg" }; string fileext = path.getextension(file.filename).tolower(); if (array.indexof(validext, fileext) < 0) { return; } if (file.contentlength / 1024 > 5120) { return; } string path = server.mappath("~/upload/image_upload/ads/"); string[] s = file.filename.split('\\'); filename = system.io.path.getfilename(s[s.length - 1]); while (system.io.file.exists(path + filename)) { random r = new random(); int rn = (datetime.now + r.next().tostring()).gethashcode(); filename = rn + " " + filename; } string fullpath = path + filename; file.saveas(fullpath); imageresize.resizeimage(fullpath, fullpath, 800, 80); string thpath = path + "th\\" + filename; file.saveas(thpath); imageresize.resizeimage(thpath, thpath, 300, 90); } sqlconnection con = new sqlconnection(cs); stringbuilder sb = new stringbuilder(); sb.append("begin try begin transaction"); sb.append(" declare @result bit=0; declare @ad_id int;"); sb.append("insert tbl_ads(ad_title,ad_brief,ad_text,ad_pic,ad_datesave,ad_is_accept,ad_is_show,ad_visit,ad_type,ad_user,ad_is_slide)"); sb.append(" values(@ad_title,@ad_brief,@ad_text,@ad_pic,@ad_datesave,@ad_is_accept,@ad_is_show,@ad_visit,@ad_type,@ad_user,@ad_is_slide);"); sb.append("set @ad_id=scope_identity();"); sqlcommand cmd = new sqlcommand(); cmd.connection = con; cmd.parameters.addwithvalue("@ad_title", txt_title.value); cmd.parameters.addwithvalue("@ad_brief", txt_brief.value); cmd.parameters.addwithvalue("@ad_text", txt_full.value); cmd.parameters.addwithvalue("@ad_pic", filename); cmd.parameters.addwithvalue("@ad_datesave", persiandate.getdate(0)); cmd.parameters.addwithvalue("@ad_is_accept", chk_accept.checked); cmd.parameters.addwithvalue("@ad_is_show", chk_show.checked); cmd.parameters.addwithvalue("@ad_visit", 0); cmd.parameters.addwithvalue("@ad_type", lst_type.value); cmd.parameters.addwithvalue("@ad_user", -1*(int)session["u_id"]); cmd.parameters.addwithvalue("@ad_is_slide", chk_slide.checked); string[] subcatids = inp_subcats.value.split(','); string[] stateids = inp_states.value.split(','); string[] cityids = inp_cities.value.split(','); if (catids[0] != "") { (int = 0; < catids.length; i++) { cmd.parameters.addwithvalue("@cat_id" + i, catids[i]); sb.append("insert tbl_inf_adcat(ad_id,cat_id) values(@ad_id,@cat_id" + + ");"); } } if (subcatids[0] != "") { (int = 0; < subcatids.length; i++) { cmd.parameters.addwithvalue("@subcat_id" + i, subcatids[i]); sb.append("insert tbl_inf_adsubcat(ad_id,subcat_id) values(@ad_id,@subcat_id" + + ");"); } } if (stateids[0] != "") { (int = 0; < stateids.length; i++) { cmd.parameters.addwithvalue("@state_id" + i, stateids[i]); sb.append("insert tbl_inf_adstate(ad_id,state_id) values(@ad_id,@state_id" + + ");"); } } if (cityids[0] != "") { (int = 0; < cityids.length; i++) { cmd.parameters.addwithvalue("@city_id" + i, cityids[i]); sb.append("insert tbl_inf_adcity(ad_id,city_id) values(@ad_id,@city_id" + + ");"); } } sb.append("commit set @result=1 select @result end try begin catch if @@trancount > 0 rollback select @result end catch"); cmd.commandtext = sb.tostring(); try { con.open(); bool result = convert.toboolean(cmd.executescalar()); if (result == true) { clientalert.modalboxinfo(this, "success"); } else { clientalert.modalboxalert(this, "error"); } } catch { clientalert.modalboxalert(this, "error"); } { con.close(); } }
but when want run method error occur :
an asynchronous module or handler completed while asynchronous operation still pending.
i used async="true" in page directive , test in visual studio in real host has error. because used transaction? advance regards.
no, it's because of
await task<int>.factory.fromasync(stream.beginread, stream.endread, buffer, 0, buffer.length, null);
the tricky part async
method returning void
. that's big no-no unless know you're doing (which don't right now). have return task
instead, , same other callers way request handler itself. allow marshal awaited callback original request thread - otherwise, request end, causing callback work on completed request.
for await
code work correctly, need have unbroken chain of task
-returning methods, simple that. otherwise, @ point you're calling void
-returning method returns , continue on next statement, while background task still running.
or, if want fire-and-forget action, without having request wait resize done, can force await
not try marshalling request thread:
await task<int>.factory.fromasync(stream.beginread, stream.endread, buffer, 0, buffer.length, null).configureawait(false);
also, it's bad idea save input file file first. have need work input stream directly, why want save intermediate file? quite fail on file locking issue.
and, when using such fire-and-forget tasks, make sure proper error handling. depending on .net framework version , configuration, unhandled exception in non-awaited task
kill whole process.