Board logo

Subject: 匿名过程转换成事件过程的意义和方法 [Print This Page]

Author: zzzl    Time: 2011-1-5 00:14     Subject: 匿名过程转换成事件过程的意义和方法

先贴一小段例子说明这个方法的意义

procedure TForm1.Button1Click(Sender: TObject);
var
    s: string;
begin
s:='aa'; //用这句表示s的值经过一个复杂的计算,得出值为aa

timer1.OnTimer:=NotifyEvent(  //给这个TTimer控件指定onTimer事件
    procedure(sender: TObject)
    begin
    memo1.Lines.Add(s+  sender.ToString);  //这里使用了s变量,是的,它能“看见”s
    end);
end;

如果用别的方法实现上面的功能,s可能会被放在TForm1宝贵的private区域,以让OnTimer事件函数能看到它。而这个方法使你可以连贯的表达你的意图:计算s的值,以某种方式显示它。你不必把这个整体的逻辑划分到两个函数里。


有很多个理由需要把一个匿名过程转换成事件类型,但delphi似乎没有直接提供这个方法,如果有谁知道的话记得告诉我。


//////////////////////////////////////////////////////////////////////////////////////////////////////////////

我自己的实现方法很简单,也很笨,代码很短,贴出来了

_CPack=class(TComponent)  //这个类不应被客户端看到,它只为NotifyEvent函数使用,所以我在前面加了个下划线。
private
    fProc: TProc<TObject>;
    procedure event(sender: TObject);
end;

procedure _CPack.event(sender: TObject);
begin
fProc(sender);
end;

function NotifyEvent(p: TProc<TObject>): TNotifyEvent;
var
    obj: _CPack;
begin
obj:=_CPack.Create(Application);
obj.fProc:=p;
Result:=obj.event;
end;

这个实现方法的缺点是每调用一次NotifyEvent都要产生一个TComponent对象,不过NotifyEvent的调用次数应该是在编译时确定的,所以数量微不足道,如果要在运行时确定,你可以将NotifyEvent的返回值暂存起来用。

这个缺点对我来说不成问题,因为我在写客户端程序时倾向于不释放资源以换取稳定性。

如果你实在在意这个leak,可以给NotifyEvent加一个out id参数,有了id,你就可以控制生存期了。


另一个实现在这里(http://kindi.tistory.com/entry/Using-anonymous-methods-in-method-pointers
,韩语的,不知在说什么,但我把它的代码拷出来,上面的示例可以编译通过,也没有我上面方法的问题,但唯一的问题是,它输出的结果是“Timer1”,而不是“aaTimer1",换句话说,s的值不见了。
Author: friendlinzh    Time: 2011-8-18 10:26

procedure event(sender: TObject);




Welcome to CnPack Forum (http://bbs.cnpack.org/) Powered by Discuz! 5.0.0