PDA

View Full Version : ساختن log در thread



masoode
سه شنبه 07 اردیبهشت 1395, 04:35 صبح
سلام
من در برنامه ای که با کمک دوستان در این تاپیک (http://barnamenevis.org/showthread.php?521793-%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7-%D8%A8%D8%A7-SQL-Server-%D8%AF%D8%B1-Thread) نوشتم میخوام هر وقت exception به وجود آمد آن را در فایلی ثبت کنم. قبلا تابعی در تِرِد اصلی ساخته ام به نام WriteLog اما با رجوع به این تابع احتمالا دچار مشکل خواهم شد و همچنین نمی خواهم از تابع Synchronize استفاده کنم

procedure MThread.Execute;
var
ADOQInsert:TADOQuery;
EQuery:String;
begin
inherited;
CoInitialize(nil) ; //CoInitialize was not called

ADOQInsert := TADOQuery.Create(nil);
try
while (SQLQueue.Count > 0) and (not Terminated) do
begin
try
ADOQInsert.ConnectionString:= ConnStr;
ADOQInsert.CursorLocation := clUseServer;
ADOQInsert.LockType := ltReadOnly;
ADOQInsert.CursorType := ctOpenForwardOnly;
ADOQInsert.Close;
ADOQInsert.SQL.Clear;
EQuery := SQLQueue.Strings[0];
SQLQueue.Delete(0);
ADOQInsert.SQL.Add(EQuery);
ADOQInsert.ExecSQL;
except
on E:Exception do
begin
WriteLog('Error on Query Execution :' + #13 + 'SQL : "' + EQuery + '"' + #13 + 'Error : "' + E.Message + '"', '');
end;
end;
end;
finally
ADOQInsert.Free;
end;

CoUninitialize();
end;
چه پیشنهادی دارید؟

Mahmood_M
سه شنبه 07 اردیبهشت 1395, 05:38 صبح
محدودیتی که وجود داره اینه که نباید دو ترد به صورت همزمان از یک فایل استفاده کنند ( در یک فایل بنویسند )
یک راه اینه که شما یک کلاس TStringList داشته باشید و اون رو به مقادیرتون پر کنید و در پایان ذخیره کنید
البته برای نوشتن در TStringList هم نباید تداخل ایجاد بشه
راه جلوگیری از این تداخل، استفاده از CriticalSection هستش
به این صورت که ابتدا مثلا در کلاس ترد یک متغیر از نوع کلاس TRTLCriticalSection تعریف می کنید و در متد Create مربوط به ترد، اون رو Initialize می کنید :


type
TMyThread = class(TThread)
private
...
FileLock: TRTLCriticalSection;
public
constructor Create();
destructor Destroy; override;
end;

implementation

constructor TMyThread.Create();
begin
inherited Create(True);
InitializeCriticalSection(FileLock);
end;


هر جایی که نیاز به نوشتن در فایل بود ابتدا وارد CriticalSection میشید و در انتها ازش خارج میشید :

EnterCriticalSection(FileLock);
try
WriteToLogFile();
{ ... Work with File ... }
finally
LeaveCriticalSection(FileLock);
end;
و در انتهای کار Thread اون رو Delete می کنید :

destructor TMyThread.Destroy;
begin
inherited Destroy;
DeleteCriticalSection(FileLock);
end;

اگر از چند ترد برای نوشتن Log استفاده می کنید، بهتره CriticalSection رو به صورت عمومی تعریف کنید و یا یک کلاس جدا فقط برای ویرایش فایل Log بسازید و CS رو درون اون ایجاد و استفاده کنید
درواقع باید یک CS داشته باشید که جلوی دسترسی چند ترد به یک فایل رو بگیره