【问题标题】:Any alternative to callbacks for UI programming?UI编程回调的任何替代方法?
【发布时间】:2011-01-20 11:48:11
【问题描述】:

假设我有几个步骤,例如在软件安装期间。

每一步都显示一个文本框,等待用户点击“下一步”按钮。

执行此操作的标准方法是使用如下回调:

process
{
   Dialog1() // Will call callback2 when closed
}

callback2()
{
   Dialog2()  // Will call callback3 when closed
}

callbak3()
{
   Dialog3()  // Will call callback4 when closed
}

当您必须执行很多步骤时,这种技术会使代码变得难以阅读 将您的进程划分为每个连续的回调函数(更不用说保存 从一个到另一个的上下文)。

什么是更容易阅读的方法?理想情况下,该过程应如下所示 这个:

process()
{
   Dialog1()
   callback1() // stop method until closed
   Dialog2()
   callback2()  // stop method until closed
   Dialog3()
   callback3()  // stop method until closed
}

问题在于您无法停止 UI 线程。任何想法或解决方法将不胜感激。

PS:这适用于 C 或 Objective C

回答

所以在感谢 Martin B 发现协程后,我找到了这个页面:https://stackoverflow.com/posts/4746722/edit 并最终使用了这个代码:

define coRoutineBegin static int state=0; switch(state) { case 0:
define yield do { state=__LINE__; return; 
                    case __LINE__:; } while (0);

define coRoutineEnd }

void process()
{
    coRoutineBegin

    Dialog1()
    yield
    Dialog2()
    yield
    Dialog3()
    yield
    Dialog4()
        yield

    coRoutineEnd
}

【问题讨论】:

  • 我讨厌 C 没有功能结构。这可以使用 continuations 以函数式语言(例如 javascript)完美表达。

标签: c design-patterns user-interface callback


【解决方案1】:

您正在寻找coroutines,它提供了您正在寻找的概念:在不退出函数的情况下让出控制权。本质上,您的代码如下所示:

process()
{
   Dialog1()
   yield
   Dialog2()
   yield
   Dialog3()
}

不幸的是,C 或 Objective C 本身并不支持协程,并且如果不求助于丑陋的 hack,就很难通用地实现协程。但是,您可以将这个概念作为针对您的情况的特殊情况构造的起点。

【讨论】:

  • 实际上,以“回调”方式设计对话框称为延续传递样式(google这个术语)。协程通常使用 CPS 实现。一种好方法是将描述下一步做什么的回调(continuation)传递给对话例程。问题是 C 没有函数式结构来干净利落地做到这一点。
  • 这看起来很有趣。我以前从未听说过协程。
【解决方案2】:

您可以使用 Mutex 或类似的概念来打开对话框并在不同的线程中运行。

这是一个我认为有效的示例的帖子:

Synchronization/wait design for cross-thread event signaling (Obj-C)?

【讨论】:

    【解决方案3】:

    我不太明白这个问题。为什么不显示模态对话框?模态对话框会一直阻塞,直到它们被解除,因此您的逻辑如下所示:

    Dialog1()
    Dialog2()
    Dialog3()
    

    另一个解决方案是让您的对话或回调或任何发送事件。然后绑定到这些事件。您的主要逻辑将如下所示(抱歉,我不知道如何在 C/Objective-C 中做 GUI 示例,所以我将使用 Tcl/Tk,因为它的可读性很高):

    bind $rootWindow <<Step1>> showDialog1
    bind $rootWindow <<Step2>> showDialog2
    bind $rootWidow <<Step3>> showDialog3
    # kick off the first step
    event generate $rootWindow <<Step1>> 
    

    showDialogX 函数会做他们需要做的任何事情,然后生成一个事件,说“我已经完成了,准备好进行下一步了”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多