كيفية بدء / إيقاف موضوع Delphi المراقبة عند الطلب؟

StackOverflow https://stackoverflow.com/questions/1734644

  •  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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top