to nealzhao(): 不好意思,我用Delphi时间不长,COM了解也不多。简单的CallBack在Win98/2000下都没问题,加入到 我的应用中后,Server/Client在Win98下不Marshal /Unmarshal接口也可以,但Win2000就需要Marshal /Unmarshal接口,这就需要保存IStream(也没用过)。这已经折腾我一周了,每每总有希望,实在不甘心放 弃CallBack方式。看来也只有改用COM事件了,还请你 多指教。有些文档说COM事件比较复杂,且不能通知多个Client, 一般避免使用...是这样吗?
从COM本身来说是支持CallBack(多客户)方式的。但是我没有实战过。 我正在查些资料。 1.你用“msdn wicked code"在MSDN上查一下。有一个Eight Lessons from the COM School of Hard Knocks的文章,先看看。 2.在www.codeproject.com上有关于IConnectionPoint的文章和例子,也可以参考。 3.另外你的IStream,可以使用一个全局变量,只有当前的进程没推出,她一直存在。 希望有些帮助。
...
FmtsCallBack := TmtsCallBackClient.Create;
(应为 FmtsClient := TmtsClient.Create;)
...
在你地工作完成后释放消息队列UnInitialize,如果是多线程模式地相应地必须初始化多线程地消息队列,在结束地时候释放消息队列!
(1) ImtsClient传递到Server.SetCallBack(此时可以回调),
此时Marshal, 结束本次调用。
(2) Server.GetData被调用(也可能是另一个Client),此时
Unmarshal,可以回调。现在的问题是:
ImtsClient要重复使用,如何保存Marshal后的IStream???
,对象应该是无状态的(理想)。
你常在网上?我还怕一时找不到你呢。CSDN有了你才昌盛。是我省略了代码,未表达清我的意图,我的用法是:
(1)每个Client登陆后,把各自的ImtsClient通过Server.SetCallBack
传递到Server待用,结束SetCallBack调用;对象是无状态的,那就要保
存手工保存状态(ImtsClient)。
(2)当有Client更新数据时,通知所有相关的Client刷新本地数据。保存状态(ImtsClient):
(1) 用ISharedProperty我不知道如何保存IStream。
(2) 用文件保存Unmarshal时出错,代码如下:procedure TmtsServer.SetCallBack(vClientName, vCallBack: OleVariant);
var
fstm: TFileStream;
ostm: TOleStream;
stm: IStream;
begin
try
OleCheck(CoMarshalInterThreadInterfaceInStream
(ImtsClient, vCallBack, stm));
ostm := TOleStream.Create(stm);
fstm := TFileStream.Create('C:\' + vClientName, fmCreate);
fstm.Position := 0;
fstm.CopyFrom(ostm, 0);
fstm.Free;
ostm.Free;
SetComplete;
except
SetAbort;
raise;
end;
end;procedure TmtsServer.GetData(out vData: OleVariant); safecall;
begin
try
fstm := TFileStream.Create('C:\' + vClientName,
fmOpenReadWrite);
ostm := TOleStream.Create(stm);
ostm.Position := 0;
ostm.CopyFrom(fstm, 0); OleCheck(CoGetInterfaceAndReleaseStream(stm,
ImtsCallBackClient, mtsCallBack));
//???报错:读磁盘错 mtsCallBack.SynchNotify(cds.Data);
fstm.Free;
ostm.Free; vData := ... SetComplete;
except
SetAbort;
raise;
end;
end;
不好意思,我用Delphi时间不长,COM了解也不多。简单的CallBack在Win98/2000下都没问题,加入到
我的应用中后,Server/Client在Win98下不Marshal
/Unmarshal接口也可以,但Win2000就需要Marshal
/Unmarshal接口,这就需要保存IStream(也没用过)。这已经折腾我一周了,每每总有希望,实在不甘心放
弃CallBack方式。看来也只有改用COM事件了,还请你
多指教。有些文档说COM事件比较复杂,且不能通知多个Client,
一般避免使用...是这样吗?
我正在查些资料。
1.你用“msdn wicked code"在MSDN上查一下。有一个Eight Lessons from the COM School of Hard Knocks的文章,先看看。
2.在www.codeproject.com上有关于IConnectionPoint的文章和例子,也可以参考。
3.另外你的IStream,可以使用一个全局变量,只有当前的进程没推出,她一直存在。
希望有些帮助。
相关的Client刷新本地数据,这时是另一次Server方法调用。每个Client登陆后,把各自的ImtsClient通过Server.SetCallBack
传递到Server待用,方法调用结束,对应本次线程是否结束?还是Client端Create一个IServer后,Server就有一个对应线程,直到
Clientt端Release该IServer?
将在Client的Create中创建Server对象并且建立与Server的联系。
将其移到外边(第三方组件,客户端程序中)
我还是先用NotePad写比较保险。to nealzhao():你说的我已试过,还是不行。我试了一种方式://保存ImtsClient
procedure TmtsServer.SetCallBack(vCookie, vCallBack: OleVariant);
var
sp: ISharedProperty;
bExist: WordBool;
stm, stm2: IStream;
ostm, ostm2: TOleStream;
h: HGLOBAL;
begin
try
OleCheck(CoMarshalInterThreadInterfaceInStream(ImtsClient, vCallBack, stm));
ostm := TOleStream.Create(stm);
h := GlobalAlloc(GMEM_MOVEABLE + GMEM_NODISCARD + GMEM_SHARE, ostm.Size);
OleCheck(CreateStreamOnHGlobal(h, False, stm2));
ostm2 := TOleStream.Create(stm2);
ostm2.Position := 0;
ostm2.CopyFrom(ostm, 0); sp := FspgCallBack.CreateProperty(<ClientName>, bExist);
sp.Value := Int(h); SetComplete;
ostm.Free;
ostm2.Free;
except
SetAbort;
ostm.Free;
ostm2.Free;
raise;
end;
end;//回调ImtsClient
procedure TmtsServer.SynchNotify;
var
sp: ISharedProperty;
bExist: WordBool;
I: Integer;
stm: IStream;
mtsCallBack: ImtsClient;
begin
try
sp := FspgCallBack.CreateProperty(<ClientName>, bExist);
if bExist and not VarIsNull(sp.Value) then
begin
OleCheck(CreateStreamOnHGlobal(LongWord(sp.Value), False, stm));
OleCheck(CoUnmarshalInterface(stm, ImtsClient, mtsCallBack));
mtsCallBack.SynchNotify(...);
end
else
sp.Value := Null;
end;
finally
cds.Free;
end;
end;但是在第二次回调时出错:“被调用对象已与其客户断开连接”
我采用了苯法避开,Client在传送一次ImtsClient(用Server.SetCallBack)
未完全测试,暂时Server/Client在同一PC(Win2000)下通过。我现在担心的是:
(1)用CoUnmarshalInterface而不用CoGetInterfaceAndReleaseStream
是否可以?(用CoGetInterfaceAndReleaseStream产生内存存取错)
(2)CreateStreamOnHGlobal使用是否正确?
(3)...哎,主要还是我对COM不懂,仅限于用Delphi创建个简单的MTS/COM+应用,
也没时间学就开做,结果倒误事了,多亏有CSDN的同志们帮忙。还希望继续得到同志们的指教,多谢!!!
1,开始时工程时使用的线程模式?
2,开始时工程使用的实例模式?
3,apartment 的transaction 模式?suppor?new?...
4, 我觉得要是保留状态的话,使用shared property group manager 是最好的选择,因为mts内部的很多机制我们也不是很精通?
5,注意客户端的transaction,否则客户端会去连接一个已经释放的对象,因为mts使用了很多pooling技术。这些都只是参考!
>2,开始时工程使用的实例模式?initialization
TAutoObjectFactory.Create(ComServer, TmtsServer, Class_mtsServer,
ciMultiInstance, tmApartment);>3,apartment 的transaction 模式?suppor?new?...
>4, 我觉得要是保留状态的话,使用shared property group manager 是最好
>的选择,因为mts内部的很多机制我们也不是很精通?
我把IStream放在HGLOBAL指向的内存中,而在sp.Value中保存HGLOBAL指针,是因为我不知如何用sp.Value保存IStream。我的应用中用了几组 shared property,但其会自动释放,下一步还得这个问题,你是如何解决的?
>5,注意客户端的transaction,否则客户端会去连接一个已经释放的对象,
>因为mts使用了很多pooling技术。
我不理解“客户端的transaction”(因为我对Delphi和MTS/COM+所知有限)。
至于客户端的transaction,如果为new,只要客户端技术以后需要重新连接,那么就要重新建立com+对象,无论原来的是否已经释放,如果suppor,如果还有就使用原来的,如果non_support,那么有就连接,没有就连接失败。我觉得也可能和客户端的transaction有关。
A->B->A这种情况。
你可否做个判断,不去调用请求数据更新地Client地CallBack。
2.也许你可以考虑一下这个结构。
单独创建一个CallBackServer地MTS对象管理回调问题。
ICallBackServer = interface
Advise( aClient : ICallBackIntf; aCookie : PInteger);
UnAdvise( aCookie : PInteger);
UpdateClient;
end;
这个组件单独地放在一个Package中,TimeOut时间设为无限。
一个MTS组建。UpdateData时回调Client更新数据。
如果要实用还需要加入共享资源保护的代码...
不知道对你有没有帮助。
如果需要我可以email给你
不好意思,刚上网。我周日陪家里客人,未到公司。
上班比较累,所以我家里未有PC.感谢大家的帮助,我对MTS/COM+还比较模糊,还不能与各位很好对话,
我先应付任务,然后赶快比较系统地学习MTS/COM+后,再向你们请教,
并改进我的程序。我想多给分,如何给?如果另贴又怕被删除。to nealzhao() :
非常需要,我的email:[email protected]
多谢!!!
我已收到,对我很有用,再次表示感谢!!!
manboo(折翼天使在红叶飞舞)
wolfhe(城墙)