Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.07.14;
Скачать: [xml.tar.bz2];

Вниз

Неосвобождается com сервер.   Найти похожие ветки 

 
Erik   (2003-07-01 13:39) [0]

Я создал com сервер и клиент с некоторыми особеностями. Которые заключаются в создании списка инстанций сервера и клиента. Для каждого отдельно! Разумеется с маршалингом для того чтобы сервер мог перебрать всех своих клиентов. И еще реализован CallBack.
Код сервера:
TProtocol = class(TRemoteDataModule, IProtocol)
.....
procedure RemoteDataModuleCreate(Sender: TObject);
procedure RemoteDataModuleDestroy(Sender: TObject);
....
private
DBMain: TMainData;
fLoggedIn: Boolean;
fUserID: Integer;
fUserName: String;
fKohtID: Integer;
Kuupaev: Cardinal;
FMarshaler: TInterThreadMarshaler; // Callback
procedure CreateUserData;
protected
procedure SetCallBack(AValue: OleVariant); safecall;
function Login(const User, Password: WideString; var ID: Integer): RetStatus; safecall;
function SetKoht(Koht_ID: Integer): WordBool; safecall;
public
constructor Create(AOwner: TComponent); override;
function SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult; override;
procedure CallBack(StTerminate: Boolean);
end;

Function AllReady(const User_ID, Koht_ID: Integer; var Index: Integer): RKohtStatus;

Var
Protocol: TProtocol;
ReservAeg: TReservAeg = nil;
List: TThreadSafeList = nil;
Count: Integer = 0;
...
constructor TProtocol.Create(AOwner: TComponent);
begin
if Count = 0 then begin
if not Assigned(MainData) then begin
MainData := TMainData.Create(nil);
inherited Create(AOwner);
DBMain := MainData;
end;
end else
inherited Create(AOwner);
end;

procedure TProtocol.RemoteDataModuleCreate(Sender: TObject);
begin
Inc(Count);
FMarshaler := TInterThreadMarshaler.Create(IDispatch);
FLoggedIn := False;
List.Add(Sender);
fUserID := Count; //List.Count;
if Assigned(Alarm) and Alarm.Suspended then
Alarm.Resume;
end;

procedure TProtocol.RemoteDataModuleDestroy(Sender: TObject);
begin
Dec(Count);
LogTimeStop;
if Assigned(List) then
List.Remove(Self);

ReservAeg.DelUser(fUserID);
if Assigned(DBMain) then
Sysutils.FreeAndNil(DBMain);
if Count = 0 then
MainData := nil;
end;

function TProtocol.Login(const User, Password: WideString; var ID: Integer): RetStatus;
begin
CreateUserData;
try
DBMain.Database.Connected := False;
DBMain.Database.LogonUsername := User;
DBMain.Database.LogonPassword := Password;
DBMain.Database.Connected := True;
except on E: Exception do begin
FreeAndNil(DBMain);
Result := rtError;
raise E;
end;
end;

fUserName := User;
if ID < 1 then
ID := fUserID
else fUserID := ID;
fLoggedIn := True;
Result := rtOk;
end;

Function AllReady(const User_ID, Koht_ID: Integer; var Index: Integer): RKohtStatus;
Var i: Integer;
Server: TProtocol;
begin
Result := kohtFree;
List.BeginRead;
try
for I := 0 to List.Count-1 do begin
Server := List[i];
with Server do begin
if fKohtID = 0 then
Continue;
if (fUserID = User_ID) and (fKohtID = Koht_ID) then begin
Index := i;
Result := kohtAbort;
Break;
end else if (fUserID <> User_ID) and (fKohtID = Koht_ID) then begin
Index := i;
Result := kohtExist;
Break;
end;
end;
end;
finally
List.EndRead;
end;

end;

function TProtocol.SetKoht(Koht_ID: Integer): WordBool;
var Status: RKohtStatus;
Index: Integer;
begin
Result := True;
if Koht_ID = 0 then
exit;
Status := AllReady(fUserID, Koht_ID, Index);
if Status = kohtAbort then
TProtocol(List[Index]).CallBack(Status = kohtAbort)
else
Result := Status = kohtFree;

fKohtID := Koht_ID;
LogTimeStart;
end;

procedure TProtocol.CallBack(StTerminate: Boolean);
var Intf: Variant;
User_ID, Koht_ID: Integer;
begin
if not Assigned(FMarshaler.Unknown) then
exit;
Intf := IDispatch(FMarshaler.Unknown);
if StTerminate then
FMarshaler.Clear;
Intf.DoExists(User_ID, Koht_ID, StTerminate);

if not StTerminate and (fKohtID<>0) and ((User_ID <> fUserID) or (Koht_ID <> fKohtID)) then
begin
StTerminate := True;
Intf.DoExists(User_ID, Koht_ID, True);
end;

if StTerminate then
FMarshaler.Clear;
end;

.....

initialization
ReservAeg := TReservAeg.Create;
List := TThreadSafeList.Create;

DataLockup.Lookup := DataLockup.TDataLookup.Create(nil);
TComponentFactory.Create(ComServer, TProtocol, Class_Protocol, ciMultiInstance, tmApartment); //tmApartment tmBoth tmSingle
ComServer.UIInteractive := False;

finalization
if Assigned(List) then
FreeAndNil(List);
FreeAndNil(ReservAeg);
FreeAndNil(DataLockup.Lookup);

CallBack - снимает задачу но счетчик сылок неуменьшается!
При простом выходе их клиента и закрытии DCOMСonnection тоже самое!


 
Erik   (2003-07-01 13:44) [1]

Привожу еще код класса TThreadSafeList.
TThreadSafeList = class
private
FLock: TMultiReadExclusiveWriteSynchronizer;
FItems: TList;
FEmptyHandle, FNotEmptyHandle: THandle;
function GetCount: Integer;
function GetItem(Index: Integer): Pointer;
procedure SetEmpty(Value: Boolean);
public
constructor Create;
destructor Destroy; override;
procedure BeginRead;
procedure EndRead;
procedure BeginWrite;
procedure EndWrite;
function IndexOf(Item: Pointer): Integer;
function Add(Item: Pointer): Integer;
procedure Delete(Index: Integer);
procedure Insert(Index: Integer; Item: Pointer);
procedure Remove(Item: Pointer);
procedure Clear;
property Count: Integer read GetCount;
property Items[Index: Integer]: Pointer read GetItem; default;
property EmptyHandle: THandle read FEmptyHandle;
property NotEmptyHandle: THandle read FNotEmptyHandle;
end;

{ TThreadSafeList }
constructor TThreadSafeList.Create;
begin
FLock := TMultiReadExclusiveWriteSynchronizer.Create;
FEmptyHandle := CreateEvent(nil, True, True, nil);
FNotEmptyHandle := CreateEvent(nil, True, False, nil);
end;

destructor TThreadSafeList.Destroy;
begin
Clear;
FLock.Free;
CloseHandle(FEmptyHandle);
CloseHandle(FNotEmptyHandle);
inherited;
end;

procedure TThreadSafeList.SetEmpty(Value: Boolean);
begin
if Value then
begin
SetEvent(FEmptyHandle);
ResetEvent(FNotEmptyHandle);
end else begin
ResetEvent(FEmptyHandle);
SetEvent(FNotEmptyHandle);
end
end;

function TThreadSafeList.GetCount: Integer;
begin
BeginRead;
try
Result := ListCount(FItems);
finally
EndRead;
end;
end;

function TThreadSafeList.GetItem(Index: Integer): Pointer;
begin
BeginRead;
try
Result := ListItem(FItems, Index);
finally
EndRead;
end;
end;

function TThreadSafeList.IndexOf(Item: Pointer): Integer;
begin
BeginRead;
try
Result := ListIndexOf(FItems, Item);
finally
EndRead;
end;
end;

procedure TThreadSafeList.BeginRead;
begin
FLock.BeginRead;
end;

procedure TThreadSafeList.EndRead;
begin
FLock.EndRead;
end;

procedure TThreadSafeList.BeginWrite;
begin
FLock.BeginWrite;
end;

procedure TThreadSafeList.EndWrite;
begin
FLock.EndWrite;
end;

function TThreadSafeList.Add(Item: Pointer): Integer;
begin
BeginWrite;
try
Result := Count;
Insert(Result, Item);
finally
EndWrite;
end;
end;

procedure TThreadSafeList.Delete(Index: Integer);
begin
BeginWrite;
try
ListDelete(FItems, Index);
finally
EndWrite;
end;
end;

procedure TThreadSafeList.Insert(Index: Integer; Item: Pointer);
begin
BeginWrite;
try
ListInsert(FItems, Index, Item);
SetEmpty(False);
finally
EndWrite;
end;
end;

procedure TThreadSafeList.Clear;
begin
BeginWrite;
try
ListClear(FItems);
SetEmpty(True);
finally
EndWrite;
end;
end;

procedure TThreadSafeList.Remove(Item: Pointer);
begin
BeginWrite;
try
if ListIndexOf(FItems, Item) >= 0 then
begin
ListRemove(FItems, Item);
SetEmpty(FItems = nil);
end;
finally
EndWrite;
end;
end;



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.07.14;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.47 MB
Время: 0.009 c
1-44704
kull
2003-06-30 12:34
2003.07.14
Как послать письмо с аттачем через ShellExecute?


3-44575
Пубертанец
2003-06-20 13:48
2003.07.14
Как программно в TTable добавить lookup-овское поле?


14-44860
Pat
2003-06-22 01:19
2003.07.14
Дорожный налог


3-44540
Cranium
2003-06-19 12:12
2003.07.14
Один юзер - один коннект.....


1-44669
Vint45
2003-07-02 14:23
2003.07.14
Функции для дин.массивов





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский