c# - Performing work asynchronously in .NET 4 -
i have legacy code performs long operations on ui thread. want show progress bar message , run work on thread. unfortunately , don't have access vs2012 can't utilize async keyword. i've written code works fine operations of 0-1 parameters , no homecoming value using action. when tried adjusting back upwards func encountered issues invoking tasks , returning tresult. attached original code, appreciate suggestions. thanks, omer
public partial class freeprogressbarfrm : system.windows.forms.form { #region members /// <summary> /// timer progress bar. /// </summary> private timer m_timer = new timer(); /// <summary> /// delegate background operation perform. /// </summary> private action m_backgroundoperation; /// <summary> /// standard operation show user while operation in progress. /// </summary> private static readonly string m_performingupdatesmessage = io_global.getresourcestring("performing updates, please wait", "performing updates, please wait", null); #endregion #region constructor /// <summary> /// constructor /// </summary> /// <param name="backgrounddelegate"> delegate background operation perform</param> /// <param name="operationname">meessage show user while operation in progress.</param> public freeprogressbarfrm(action backgrounddelegate, string operationname) { initializecomponent(); m_backgroundoperation = backgrounddelegate; this.formborderstyle = system.windows.forms.formborderstyle.none; this.lbloperation.text = operationname; m_timer.interval = 1000; m_timer.tick += new eventhandler(m_timer_tick); } /// <summary> /// constructor , progressbar defalt user message (performing updates, please wait). /// </summary> /// <param name="backgrounddelegate"> delegate background operation perform</param> /// <param name="operationname">operation display name</param> public freeprogressbarfrm(action backgrounddelegate): this(backgrounddelegate, m_performingupdatesmessage) { } #endregion #region methods /// <summary> /// phone call method begin backgorund operation while /// showing progress bar client. /// </summary> public void wait() { showdialog(controlshelper.mainfrm); } /// <summary> /// advance progress bar /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void m_timer_tick(object sender, eventargs e) { performstep(); } /// <summary> /// advance progress bar /// </summary> private void performstep() { this.progressbar1.performstep(); this.lbloperation.refresh(); if (this.progressbar1.value == this.progressbar1.maximum) { this.progressbar1.value = this.progressbar1.minimum; } } /// <summary> /// load form , start progress bar , backroud task. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void progressbarfrm_load(object sender, eventargs e) { m_timer.start(); this.lbloperation.refresh(); task task = new task(m_backgroundoperation); task uitask = task.continuewith(delegate { onworkcompleted(); }, taskscheduler.fromcurrentsynchronizationcontext()); seek { task.start(); } grab (exception) { close(); throw; } } /// <summary> /// called when work has been completed. /// </summary> private void onworkcompleted() { close(); } /// <summary> /// close timer. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void progressbarfrm_formclosing(object sender, formclosingeventargs e) { if (m_timer != null) { m_timer.dispose(); m_timer = null; } } #endregion }
here way i'm executing async work,
public static class taskexecuter { private static readonly threadlocal<list<backgroundtask>> taskstoexecute = new threadlocal<list<backgroundtask>>(() => new list<backgroundtask>()); public static action<exception> exceptionhandler { get; set; } public static void executelater(backgroundtask task) { taskstoexecute.value.add(task); } public static void discard() { taskstoexecute.value.clear(); } public static void startexecuting() { var value = taskstoexecute.value; var re-create = value.toarray(); value.clear(); if (copy.length > 0) { task.factory.startnew(() => { foreach (var backgroundtask in copy) executetask(backgroundtask); }, taskcreationoptions.longrunning) .continuewith(task => { if (exceptionhandler != null) exceptionhandler(task.exception); }, taskcontinuationoptions.onlyonfaulted); } } public static void executetask(backgroundtask task) { task.run(); } }
here base of operations class
public abstract class backgroundtask { protected readonly logger logger = logmanager.getcurrentclasslogger(); protected virtual void initialize() { } protected virtual void onerror(exception e) { //do work } public bool? run() { logger.info("started task: {0}", gettype().name); initialize(); seek { execute(); taskexecuter.startexecuting(); homecoming true; } grab (exception e) { logger.errorexception("could not execute task " + gettype().name, e); onerror(e); homecoming false; } { taskexecuter.discard(); logger.info("finished task: {0}", gettype().name); } } public abstract void execute(); }
here illustration of using
public class sendemailtask : backgroundtask { private const string mailserverip = "yourip"; public string[] { get; set; } public string { get; set; } public string template { get; set; } public object viewcontext { get; set; } public string[] attachments { get; set; } public string subject { get; set; } public override void execute() { mailmessage message = new mailmessage(); seek { mailaddress mailaddress = new mailaddress(from); message.from = mailaddress; foreach (string in to) message.to.add(to); message.subject = subject; if (attachments.returnsuccess()) { foreach (string attachment in attachments) message.attachments.add(new attachment(attachment)); } message.priority = mailpriority.high; message.body = template; message.alternateviews .add(alternateview .createalternateviewfromstring(viewcontext.tostring(), new contenttype("text/html"))); message.isbodyhtml = true; new smtpclient(mailserverip) { port = 25, usedefaultcredentials = true }.send(message); } grab (exception e) { logger.fatalexception("error sending email:", e); } { message.dispose(); } } public override string tostring() { homecoming string.format("to: {0}, from: {1}, template: {2}, viewcontext: {3}, attachments: {4}, subject: {5}", to, from, template, viewcontext, attachments, subject); } }
here i've added changed version needs
public static class asyncexecuter { private static readonly threadlocal<list<action>> taskstoexecute = new threadlocal<list<action>>(() => new list<backgroundtask>()); public static action<exception> exceptionhandler { get; set; } public static void executelater(backgroundtask task) { taskstoexecute.value.add(task); } public static void discard() { taskstoexecute.value.clear(); } public static void startexecuting() { var value = taskstoexecute.value; var re-create = value.toarray(); value.clear(); if (copy.length > 0) { task.factory.startnew(() => { foreach (var backgroundtask in copy) executetask(backgroundtask); }, taskcreationoptions.longrunning) .continuewith(task => { if (exceptionhandler != null) exceptionhandler(task.exception); }, taskcontinuationoptions.onlyonfaulted); } } public static void executetask(action task) { task.invoke(); } }
c# multithreading asynchronous
No comments:
Post a Comment