使用Remobjects的单通道做服务端项目时,每当同一客户端同时发起超过一个以上的请求数据时,就会出现Channel is Busy 错误,为此我询问过Remobjects官方,他们回答是,单通道是非多线程安全的,类似这样的回答,建议我的用超级通道。可是简单地更换单通道为超级通道反而导致问题更多,由是我就想改造一下单通道。
在盒子上我曾经发布关于这个问题解决方法,但是还不合理,现在贴出来最终的解决方法,这个方法在我的程序使用后,再也没有出现以上问题uROClient.pas内,请对照修改.procedure TROTransportChannel.Dispatch(aRequest, aResponse : TStream);var retry : boolean; {$ifdef REMOBJECTS_UseEncryption} EncRequest,EncResponse : TMemoryStream; {$endif} faultstartlocatoridx : integer; lEvent: TROEvent; ATime: Integer;constaIncment:Integer=10;aMaxWaitTime:Integer =100000;beginretry := TRUE;if not fThreadsafe then
_CriticalSection.Enter;//加上这一句,可能等到本次请求结束后,再执行下次请求。很实用。trybegin if fBusy then raise EROChannelBusy.Create(err_ChannelBusy); fBusy := TRUE;end;//removed because of a warning faultstartlocatoridx := -1;faultstartlocatoridx := InitServerLocator;
try
if Assigned(fOnSendStream) then fOnSendStream(aRequest);repeat
try aRequest.Position := 0;{$IFDEF REMOBJECTS_UseEncryption}
if Encryption.EncryptionMethod <> tetNone then begin EncRequest:= TMemoryStream.Create; EncResponse := TMemoryStream.Create; try DoEncryption(aRequest,EncRequest); IntDispatch(encRequest, encResponse); DoDecryption(EncResponse,aResponse); finally EncRequest.Free; EncResponse.free; end; end else {$ENDIF} begin IntDispatch(aRequest, aResponse); end;aResponse.Position := 0;
if Assigned(fOnReceiveStream) then begin fOnReceiveStream(aResponse); aResponse.Position := 0; end;Exit;
except on E:Exception do begin retry := FALSE;ChangeServerLocator(faultstartlocatoridx,retry,E);
//if not retry then begin //if Assigned(fOnException) then fOnException(Self, E, retry); if not retry then raise; //end; end; end; until not retry;finally if not fThreadSafe then fBusy := FALSE;end;finally if not fThreadSafe then _CriticalSection.Release;end;end;