お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"汎用ロックサーバ"

この発言に対し以下のコメントが寄せられています
#01317 TN さん RE:汎用ロックサーバ
#01341 TN さん RE:汎用ロックサーバ

特定の文字列に対して待ち行列を作って実行を待たせる機能を持った、 アウトプロセスのCOMサーバの例を示します。 テーブルを開いて更新するときや、ファイルに書き込むときに「開けません」 エラーを検出してポーリングを繰り返す必要が無く、トランザクションを複数 同時に受け付けてさばく場合にすっきりしたコードを記述できます。 <サーバの作成> ・プロジェクトの新規作成でオートメーションオブジェクトを作ります。 (LockServer.exe) ・タイプライブラリエディタでINamedLockというinterfaceをつくり、  下記メソッドを宣言 INamedLock = interface(IDispatch) procedure Lock(const LockName: WideString); safecall; procedure UnLock(const LockName: WideString); safecall; procedure Clear; safecall; end; ・NamedLock.pasをusesしたアプリを作成。一回実行してレジストリに登録させる。 <クライアントのコーディング> uses ...., LockServer_TLB; var NamedLock: INamedLock; NamedLock := CoCreateNamedLock; NamedLock('D:\DataFiles\File1.txt'); // ファイルのロック NamedLock('MyDB:Table1'); // テーブルのロック try //////////////////////// 仕事をする finally NamedUnLock('MyDB:Table1'); // テーブルの開放 NamedUnLock('D:\DataFiles\File1.txt'); // ファイルの開放 end; 注意 ・INamedLockを使用しないファイルやテーブルへのアクセスはまったく  自由なので、ロックし忘れた場合は無効果。 ・LockServer.exeを強制ロック解除の仕組みをつけたアプリに仕立てれば便利。  (GetLockNames、LeaveNamedLockを使えば簡単) ・DCOMでもたぶんそのまま使えるので、複数台のマシンでサーバを構成する場合  同じ文字列でファイルやテーブルにアクセスするようにしておく。 <サーバのコード>-------------------------------------------------------- { NamedLock.pas Clear method is not implemented. NamedLock server の実体 ! Lockのユーザーはこのファイルをusesしないこと. ユーザは LockServer_TLB をusesすること. Lock,UnLock 文字列によるロック。大文字小文字は区別しない  あとからロックを要求するスレッドは,先取したスレッドが UnLock するまで  待たされる. } unit NamedLock; interface uses Windows, SysUtils, Classes, SyncObjs, ComObj, ComServ, ActiveX, Forms, LockServer_TLB; type TNamedLock = class(TAutoObject, INamedLock) protected procedure Lock(const LockName: WideString); safecall; procedure UnLock(const LockName: WideString); safecall; procedure Clear; safecall; end; ENamedLockException = class(Exception) end; TNamedLockEvent = procedure(LockName: string) of object; procedure LeaveNamedLock(const LockName: string); procedure GetLockNames( St: TStrings ); var Names: TStringList; //-------------------------------------------------------------------------- implementation const NORMALMAXWAITTIME = 60000; //ms 1min var NLock: TCriticalSection; // LeaveEvent: TEvent; procedure EnterNamedLock(const LockName: String); var index: integer; S: string; Result: boolean; WakeupEvent: TEvent; begin S := AnsiUppercase(LockName); Result := False; WakeupEvent := nil; NLock.Enter; try index := Names.IndexOf(S); if index = -1 then begin Names.AddObject( S, TList.Create ); // List is a queue of waiting events Result := True; end else begin WakeupEvent := TSimpleEvent.Create; TList(Names.Objects[index]).Add( WakeupEvent ); end; finally NLock.Leave; end; if WakeupEvent <> nil then begin try if WakeupEvent.WaitFor(NORMALMAXWAITTIME) = wrSignaled then begin Result := True; end; finally WakeupEvent.Free; end; end; if not Result then begin raise ENamedLockException.Create( 'NamedLock Timeout: '+ AnsiUppercase(LockName) ); end; end; procedure LeaveNamedLock(const LockName: string); var index: integer; S: string; List: TList; WakeupEvent: TEvent; begin WakeupEvent := nil; S := AnsiUppercase(LockName); NLock.Enter; try index := Names.IndexOf(S); if index <> -1 then begin List := TList(Names.Objects[index]); if List.Count = 0 then begin List.Free; Names.Delete( index ); end else begin WakeupEvent := List[0]; List.Delete(0); end; end; finally NLock.Leave; end; if WakeupEvent <> nil then begin WakeupEvent.SetEvent; end; end; procedure Clear; begin end; procedure GetLockNames( St: TStrings ); begin NLock.Enter; try St.Assign( Names ); finally NLock.Leave; end; end; { TNamedLock } procedure TNamedLock.Clear; begin //Clear; not implemented yet end; procedure TNamedLock.Lock(const LockName: WideString); begin EnterNamedLock(LockName); end; procedure TNamedLock.UnLock(const LockName: WideString); begin LeaveNamedLock(LockName); end; initialization Names := TStringList.Create; NLock := TCriticalSection.Create; // This application is outprocess NamedLock Server CoInitFlags := COINIT_MULTITHREADED; TAutoObjectFactory.Create(ComServer, TNamedLock, Class_NamedLock, ciMultiInstance, tmFree); finalization NLock.Free; Names.Free; end. TN(CQJ01721)  Original document by TN 氏 ID:(CQJ01721)



ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum