0

我正在寻找一个可中断的、延迟的事件,我希望它已经是 Spring4D 的一部分,或者在那里很容易实现。

无论如何,实现这一目标的最佳方法是什么?

可能事件不会是正确的地方。

基本上在寻找类似的东西

Event.InvokeDelayed(1000, nil); Event.InvokeCancel;

    procedure TTestMulticastEvent.Test;
    var
      e: Event<TNotifyEvent>;
    begin
      e.Add(HandlerA);
      e.Invoke(nil); // Yes, this is the normal behaviour

      // But would this make sense in Events,
      // or better use other concept, like TTask.IdleWorker, e.g. ?
      e.InvokeDelayed(1000, nil); // waits 1sec
      Sleep(100);  // Interrupts after 100ms
      e.InvokeCancel; // Prevent future Event, started earlier

    end;

也许我监督了一些已经可以在 S4D 中解决这个任务的东西。

罗洛

4

1 回答 1

0

不,库中的多播事件是同步的。为了让它们在所有情况下都能异步正常工作,它需要的不仅仅是延迟它们的调用,而是捕获你通过它们传递的任何数据,确保数据不会变得无效等等。

如果您需要这样的机制,您应该使用其中一个现有的库来执行异步操作。

例如,使用 PPL(仅显示概念的天真代码):

var
  e: Event<TNotifyEvent>;
  t: ITask;
begin
  e.Add(HandlerA);

  t := TTask.Run(
    procedure
    begin
      Sleep(1000);
      if t.Status <> TTaskStatus.Canceled then
        TThread.Synchronize(nil,
          procedure
          begin
            e.Invoke(nil);
          end);
    end);

  Sleep(100);
  t.Cancel;
end;

您可以根据您的需要和实际实现将其包装到您自己的例程中。但是,不可能为InvokeDelayed事件类型作为签名创建一个带有附加参数的方法,因为Event<T>.Invoke它不是一个方法,而是一个返回 T 的属性,您可以调用它(这使得它看起来像一个方法调用本身)。

除此之外的任何事情都需要保留传递给 Invoke 的参数以便稍后传递它们(在某种程度上,匿名方法对你来说是这样的),这不是微不足道的(至少在我们谈论泛型时不是这样Event<T>

于 2019-03-19T15:31:01.993 回答