كيفية بدء / إيقاف موضوع Delphi المراقبة عند الطلب؟
-
20-09-2019 - |
سؤال
لقد كنت أبحث عن طريقة لمراقبة تغييرات تسجيل محددة في دلفي. وجدت أ المحلول في about.com:
procedure TRegMonitorThread.Execute;
begin
InitThread; // method omitted here
while not Terminated do
begin
if WaitForSingleObject(FEvent, INFINITE) = WAIT_OBJECT_0 then
begin
fChangeData.RootKey := RootKey;
fChangeData.Key := Key;
SendMessage(Wnd, WM_REGCHANGE, RootKey, LongInt(PChar(Key)));
ResetEvent(FEvent);
RegNotifyChangeKeyValue(FReg.CurrentKey, 1, Filter, FEvent, 1);
end;
end;
end;
في طلبي، سأحتاج إلى البدء وإيقاف هذا الموضوع عند الطلب، لكن الكود أعلاه لا يسمح بذلك. مجرد إعداد العلم المنتهي لن تفعل.
سيكون كافيا لإخبار الخيط بطريقة أو بأخرى بالتوقف عن الانتظار، ثم حررها وإنشاء واحدة جديدة عند الحاجة. كيف يمكنني تغيير هذا الرمز لتحقيق ذلك؟
المحلول
يستخدم WaitForMultipleObjects()
مع مجموعة من حدثين بدلا من WaitForSingleObject()
. وبعد أضف حدث إعادة تعيين يدوي إلى فئة مؤشر الترابط، وإشارة إليه بعد تعيينه Terminated
ل True
. وبعد تحقق من قيمة الإرجاع التي تم الإشارة إليها من الحدثين، وتتصرف وفقا لذلك.
تعديل:
بعض رمز دلفي 2009 الحد الأدنى لإظهار الفكرة. يجب عليك إضافة SyncObjs
إلى قائمة الوحدات المستخدمة، وإضافة
fTerminateEvent: TEvent;
إلى private
قسم من فئة الخيط الخاصة بك.
constructor TTestThread.Create;
begin
inherited Create(TRUE);
fTerminateEvent := TEvent.Create(nil, True, False, '');
// ...
Resume;
end;
destructor TTestThread.Destroy;
begin
fTerminateEvent.SetEvent;
Terminate; // not necessary if you don't check Terminated in your code
WaitFor;
fTerminateEvent.Free;
inherited;
end;
procedure TTestThread.Execute;
var
Handles: array[0..1] of THandle;
begin
Handles[0] := ...; // your event handle goes here
Handles[1] := fTerminateEvent.Handle;
while not Terminated do begin
if WaitForMultipleObjects(2, @Handles[0], False, INFINITE) <> WAIT_OBJECT_0 then
break;
// ...
end;
end;
تحتاج فقط إلى إضافة الرمز في سؤالك إليه. ما عليك سوى محاولة تحرير مثيل الخيط سيفعل كل ما يلزم إلغاء حظر الموضوع (إذا لزم الأمر).
نصائح أخرى
بدلا من ذلك، يجب أن يكون لديك وقت waitforsingleobject بعد فترة. وبهذه الطريقة تستمر الحلقة وتم التحقق منها.
procedure TRegMonitorThread.Execute;
begin
InitThread; // method omitted here
while not Terminated do
begin
if WaitForSingleObject(FEvent, 1000) = WAIT_OBJECT_0 then
begin
fChangeData.RootKey := RootKey;
fChangeData.Key := Key;
SendMessage(Wnd, WM_REGCHANGE, RootKey, LongInt(PChar(Key)));
ResetEvent(FEvent);
RegNotifyChangeKeyValue(FReg.CurrentKey, 1, Filter, FEvent, 1);
end;
end;
end;
يمكن استخدام الأساليب TTHREAD.SESPEND و TTHREADUME.RESUME من الناحية النظرية لمواضيع التوقف المؤقتة، ولكن كما يعترف Delphi 2010 الآن بأنها غير آمنة للاستخدام. يرى تم إهمال TTHREAD.RESUME في Delphi-2010 ما الذي يجب استخدامه في المكان؟ و http://msdn.microsoft.com/en-us/library/ms686345٪28VS.85٪29.aspx.
هذا يعمل، فقط إجراء تغييرات صغيرة على النحو التالي والآن عند الاتصال:
TRegMonitorThread = class(TThread)
...
public
procedure Terminate; reintroduce;
...
procedure TRegMonitorThread. Terminate; // add new public procedure
begin
inherited Terminate;
Windows.SetEvent(FEvent);
end;
procedure TRegMonitorThread.Execute;
begin
InitThread;
while not Terminated do
begin
if WaitForSingleObject(FEvent, INFINITE) = WAIT_OBJECT_0 then
begin
if Terminated then // <- add this 2 lines
Exit;
...
end;
end;
end;