【问题标题】:ShowMessage() behavoir in FireMonkey on iOSiOS 上 FireMonkey 中的 ShowMessage() 行为
【发布时间】:2018-04-27 21:04:57
【问题描述】:

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

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

当我在 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 的应用程序启动看门狗计时器上遇到问题。

为什么会发生这种行为?

【问题讨论】:

    标签: firemonkey c++builder-10.2-tokyo


    【解决方案1】:

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

    根据10.2 Tokyo documentation

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

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

    在移动平台上ShowMessage 的行为是异步的。调用立即结束,它不等待用户关闭对话框

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

    根据10.0 Seattle documentation

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

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


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

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

    ShowMessage()(和MessageDlg())是deprecated in 10.1 Berlin

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


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

    【讨论】:

    • 雷米 - 非常感谢。你是名副其实的主人。如果没有您的耐心帮助,我会在开始使用此 IDE 之前放弃。所以 TThread 不会启动一个新线程。它看起来像您解释的另一个主题的早期帖子 TThread::ForceQueue 用于延迟分配,直到 FormShow() 退出之后。这就是这里发生的情况吗,StartupCode() 直到 FormShow 退出才开始?
    • "所以 TThread 不会启动新线程" - 我不是这么说的。我说TThread::ForceQueue() 特别不会启动新的工作线程。显然,TThread 本身就是这样做的(这是它的主要目的)。但是,是的,ForceQueue() 被用来延迟StartupCode() 的运行,直到FormShow() 退出之后。 ForceQueue() 在主 UI 线程中调用时不需要启动新的工作线程来执行该延迟(与 TThread::Queue() 不同,它仅在工作线程调用时才会延迟)。
    猜你喜欢
    • 2014-07-13
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 2013-10-22
    • 1970-01-01
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多