gpt4 book ai didi

multithreading - 在 TidHTTPServer.OnCommandGet 内创建对象(带有计时器)失败

转载 作者:行者123 更新时间:2023-12-03 13:23:18 25 4
gpt4 key购买 nike

关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。












想改进这个问题?将问题更新为 on-topic对于堆栈溢出。

1年前关闭。




Improve this question




内部 TidHTTPServer.OnCommandGet我创建了一个新对象。这个对象有一个应该立即启动但不启动的计时器。 TimerEVent 永远不会触发!
当我在其他地方创建对象时,它可以工作......
一些代码

  TVolumeFader=Class(TObject)

...
constructor TVolumeFader.Create(...);
begin
inherited Create;
...

VolTimer:=TTimer.Create(NIL);
VolTimer.Enabled:=FALSE;
VolTimer.Interval:=100;
VolTimer.OnTimer:=DoTimerTick;
end;

procedure TVolumeFader.DoTimerTick(Sender:TObject);
begin
LogWrite('TimerTick in VolumeFader',Debug);
If Assigned(VolTimer)then Begin;
VolTimer.Enabled:=FALSE;
End;
try
LogWrite('Executing VolumeFade in VolumeFader',Debug);
VolumeFade;
finally
If Assigned(VolTimer)then
VolTimer.Enabled:=TRUE;
end;
end;


procedure TMain.OnCommandGet;

Begin;
TVolumeFader.Create(...);
End;

最佳答案

在对象的构造函数中,您正在创建 TTimer好的,但您正在设置它的 Enabled属性(property)给 False .因此,请确保在构造函数退出后实际激活计时器。否则更改FalseTrue在构造函数中。
话虽如此,您的代码仍然无法如图所示工作。这是因为 TIdHTTPServer是一个多线程组件,它的OnCommand...TIdHTTPServer 的工作线程上下文中触发事件。当客户端连接到服务器时为自己创建。但是TTimer是一个基于消息的计时器,它会创建一个内部 HWND对于它自己,它与创建它的线程相关联,并且该线程必须有一个消息循环才能 TTimer处理WM_TIMER消息。您正在创建的工作线程 TTimer in 没有消息循环,所以 TTimer将无法触发其OnTimer事件。
因此,您将不得不:

  • OnCommand... 内运行您自己的消息循环创建对象后的事件处理程序,然后在事件处理程序退出之前释放对象。无法保证调用线程将在 OnCommand... 之后继续运行。事件处理程序已退出。请注意,当计时器运行时,客户端将被阻止向服务器发送任何进一步的 HTTP 命令:

  • procedure TMain.OnCommandGet(AContext: TIdContext;
    ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    var
    fader: TVolumeFader;
    msg: tagMSG;
    begin
    ...
    fader := TVolumeFader.Create(...);
    try
    while (timer should keep running) do
    begin
    //Application.ProcessMessages;
    if PeekMessage(@msg, 0, 0, 0, PM_REMOVE) then
    begin
    TranslateMessage(@msg);
    DispatchMessage(@msg);
    end else
    Sleep(100);
    end;
    finally
    fader.Free;
    end;
    ...
    end;
  • 委托(delegate)您的对象的创建,因此它的TTimer , 到您的主 UI 线程,以便您的 OnTimer事件处理程序将在该线程的上下文中触发,而不是在服务器工作线程的上下文中。只需确保您的 OnTimer代码是线程安全的,如果它需要访问与服务器共享的任何内容:

  • procedure TMain.OnCommandGet(AContext: TIdContext;
    ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    begin
    ...
    TThread.Synchronize(nil, // or TThread.Queue()
    procedure
    begin
    TVolumeFader.Create(...); // when do you destroy this object?
    end
    );
    ...
    end;

    关于multithreading - 在 TidHTTPServer.OnCommandGet 内创建对象(带有计时器)失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63851288/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com