异步调用轻量级封装AsynCaller

当UI动作引发耗时计算时,需将其放至后台线程并获取结果。使用.NET默认设施处理细节繁琐,已有解决方案不够好用,因此作者封装了AsynCaller,它通过事件通知外部异步调用结果。

当UI动作引发一个耗时的计算时,我们经常需要将这个耗时的过程放到后台线程中去完成,然后获取该过程的结果。使用.NET提供的默认设施,无论是使用Thread还是使用异步调用,细节都比较繁琐。在前几天的blog上也看到了有些兄台的解决方案,但是觉得还不够好用,于是自己封了一个AsynCaller。
AsynCaller通过事件来通知外部异步调用的结果,IAsynCaller接口如下:

publicinterfaceIAsynCaller
{
//Delegate用于动态调用目标方法
voidInitialize(Delegatemethod,object[]args);

voidStart();//启动异步操作
voidCancel();//取消操作

eventCBackTaskCompletedTaskCompleted;
eventCBackExceptionThrownExceptionThrown;
eventCBackTaskCanceledTaskCanceled;
}

publicdelegatevoidCBackTaskCompleted(objectresult);
publicdelegatevoidCBackExceptionThrown(Exceptionee);
publicdelegatevoidCBackTaskCanceled();

上面的接口清晰易懂,所需要注意的就是Initialize方法,它的第一个参数是需要进行异步调用的目标方法的委托,Delegate就像一个万能的delegate,它可以匹配到任何签名的方法。
接口出来后,其实现AsynCaller就很容易写了。
ContractedBlock.gifExpandedBlockStart.gif
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->publicclassAsynCaller:IAsynCaller
{
privateDelegatetarget=null;
privateobject[]theArgs=null;
privateThreadbackThread=null;
privateboolcanceled=false;

privateCBackTaskCompletedtaskCompleted;
privateCBackExceptionThrownexceptionThrown;
privateCBackTaskCanceledtaskCanceled;

#regionIAsynCaller成员
publicvoidInitialize(Delegatemethod,object[]args)
{
this.target=method;
this.theArgs=args;
}

publicvoidStart()
{
this.backThread=newThread(newThreadStart(this.BackThread));
this.backThread.Start();
}

publicvoidCancel()
{
this.canceled=true;
this.backThread.Abort();
}

#regionBackThread
privatevoidBackThread()
{
try
{
objectresult=this.target.DynamicInvoke(this.theArgs);//动态调用
this.ActivateTaskCompleted(result);
}
catch(Exceptionee)
{
if((this.canceled)||(eeisThreadAbortException))//任务被取消
{
this.ActivateTaskCanceled();
}
else
{
this.ActivateExceptionThrown(ee);
}
}
}
#endregion

#regionevent
privatevoidActivateTaskCompleted(objectresult)
{
if(this.taskCompleted!=null)
{
this.taskCompleted(result);
}
}

privatevoidActivateExceptionThrown(Exceptionee)
{
if(this.exceptionThrown!=null)
{
this.exceptionThrown(ee);
}
}

privatevoidActivateTaskCanceled()
{
if(this.taskCanceled!=null)
{
this.taskCanceled();
}
}

publiceventCBackTaskCompletedTaskCompleted
{
add
{
this.taskCompleted+=value;
}
remove
{
this.taskCompleted-=value;
}
}

publiceventCBackTaskCanceledTaskCanceled
{
add
{
this.taskCanceled+=value;
}
remove
{
this.taskCanceled-=value;
}
}

publiceventCBackExceptionThrownExceptionThrown
{
add
{
this.exceptionThrown+=value;
}
remove
{
this.exceptionThrown-=value;
}
}
#endregion

#endregion

}

下面给出一个示例来说明如何使用IAsynCaller。
比如在一个Form中,有两个按钮,一个用于启动异步调用,一个用于取消操作。首先写一个耗时的方法,用于异步调用:
privatevoidComputeTask(intcount)
{
for(inti=0;i<count;i++)
{
Thread.Sleep(
500);
this.label1.Text=string.Format("第{0}次",i);
}
}
然后在Form中添加成员变量:
privateIAsynCallertheAsynCaller=null;
在构造函数中,初始化theAsynCaller,并预定对应的事件:
object[]args={30};
this.theAsynCaller=newAsynCaller();
this.theAsynCaller.Initialize(newCBack1(this.ComputeTask),args);

this.theAsynCaller.TaskCanceled+=newCBackTaskCanceled(theAsynCaller_TaskCanceled);
this.theAsynCaller.TaskCompleted+=newCBackTaskCompleted(theAsynCaller_TaskCompleted);
事件处理函数如下:
privatevoidbutton1_Click(objectsender,System.EventArgse)
{
this.theAsynCaller.Start();
}

privatevoidbutton2_Click(objectsender,System.EventArgse)
{
this.theAsynCaller.Cancel();
}

privatevoidtheAsynCaller_TaskCanceled()
{
MessageBox.Show(
"TaskCanceled");
}

privatevoidtheAsynCaller_TaskCompleted(objectresult)
{
MessageBox.Show(
"Taskcomplete");
}

为了简化,上面的示例在后台线程中调用的了UI显示,这在真正的应用中是万万不可的。同时要注意,上面的示例中,IAsynCaller接口事件的事件处理函数也是在后台线程中调用的,也存在同样的问题。


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值