1

我有一个简单的 FMX 多设备 C++ 应用程序。该应用程序有 1 个表格,没有别的。在表单的OnShow事件中,我启动了一个名为 的函数StartupCode()。所有代码如下所示。

当我在Windows上运行该应用程序时,我得到了预期的行为 - 3 条消息以正确的顺序以正确的时间弹出(例如,每条消息Sleep()仅在通过单击确定确认前一个对话框后才开始)。

当我在iOSAndroid上运行该应用程序时,我会首先弹出最后一条消息(“睡了 2 秒”),但只有在整个时间过去后(12.25 秒)。然后在单击 OK 确认后立即收到“睡眠 10 秒”消息,然后同样收到“睡眠四分之一秒”消息。

#include <System.SysUtils.hpp>

void StartupCode()
{
    Sleep(250);
    ShowMessage("Slept quarter sec");
    Sleep(10000); 
    ShowMessage("Slept 10 sec");
    Sleep(2000); 
    ShowMessage("Slept 2 sec");
}

void __fastcall TForm1::FormShow(TObject *Sender)
{
    #if defined(_PLAT_IOS) || defined(_PLAT_ANDROID)
      TThread::ForceQueue(nullptr, [this](){StartupCode();});
    #endif

    #if defined(_PLAT_MSWINDOWS)
      StartupCode();
    #endif
}

我是绿色的,只是想学一点。当我遇到这种奇怪的行为时,我正在测试一个线程是否会在 Apple 的应用程序启动看门狗计时器上遇到问题。

为什么会发生这种行为?

4

1 回答 1

2

ShowMessage()只是在 10.2 Tokyo 的移动平台上的行为与您所期望的不同。

根据10.2 Tokyo 文档

ShowMessage 在不同平台上的行为不同

在桌面平台上,ShowMessage行为同步。只有当用户关闭对话框时调用才会结束。

在移动平台上ShowMessage以异步方式运行。呼叫立即结束,它不等待用户关闭对话框

如果您想在不同平台上强制执行特定行为,请使用IFMXDialogServiceAsync.ShowMessageAsyncIFMXDialogServiceSync.ShowMessageSync从该FMX.Platform单元。

根据10.0 西雅图文档

在移动平台上,呼叫ShowMessage不会被阻止。这意味着您在调用之后放置的任何代码都会ShowMessage在对话框关闭之前执行。如果您需要在对话框关闭后执行代码,请MessageDlg使用ShowMessage.

因此,在您的情况下发生的事情是您的呼叫立即ShowMessage()返回StartupCode(),在后台排队对话。然后处理所有的调用Sleep(),然后执行返回到主 UI 循环,然后同时显示所有 3 个对话框,一个在另一个上面,第一个在底部,最后一个在顶端。这就是为什么您会看到它们以相反的顺序出现。


注意:Android 不支持模态/同步对话框!因此,IFMXDialogServiceSync.ShowMessageSync()未在 Android 上实现,仅IFMXDialogServiceAsync.ShowMessageAsync()实现。

在柏林 10.1 之前,ShowMessage()内部称为同步版本 IFMXDialogService.MessageDialog()(与上述西雅图文档所说的相反),它在 iOS 上工作但ENotImplemented在 Android 上引发了异常。

ShowMessage()(and MessageDlg())在 10.1 Berlin 中被弃用

我没有安装 10.1 Berlin 或 10.2 Tokyo 来检查ShowMessage()这些系统内部的功能,但听起来它已更新为可IFMXDialogServiceAsync.ShowMessageAsync()在 iOS 和 Android 上使用,如果您在 Android 上没有遇到ENotImplemented异常。


注意:您看到的行为与TThread::ForceQueue()(顺便说一句,在 10.2 Tokyo 的 Android 上已损坏)无关。此外,TThread::ForceQueue()不会像您声称的那样启动新线程。

于 2018-04-27T22:17:25.570 回答