3

我正在使用 Pharo 在 Smalltalk 中编码。我的代码:

|i delay|
i := 0.
[i < 5] whileTrue: [
    [
        delay := Delay forSeconds: 2.
        delay wait.
        Transcript show: '2 seconds are up'.
        Transcript cr.
    ] fork.
    i := i + 1.
]

它一次打印所有“2 秒到了”,而不是每 2 秒打印一次:

2 seconds are up
2 seconds are up
2 seconds are up
2 seconds are up
2 seconds are up

拜托,谁能告诉我如何在 Smalltalk 中每 2 秒打印一些东西?

4

3 回答 3

5

您一次分叉了所有 5 个进程,以便所有 5 个延迟同时结束。要从后台每 2 秒打印一次,而是在一个单独的进程中分叉一个完整的循环:

|i delay|
[   
    i := 0.
    [i < 5] whileTrue: [
        delay := Delay forSeconds: 2.
        delay wait.
        Transcript show: '2 seconds are up'.
        Transcript cr.
        i := i + 1]
] fork
于 2012-12-01T22:06:14.417 回答
5

Janko 给出的答案当然是正确的——你立即分叉了 5 个进程,所有这些进程都等待了相同的 2 秒,所以它们都同时完成。

这里有一点解释:

[|delay|
  delay := Delay forSeconds: 2.
  5 timesRepeat: [
     delay wait.
     Transcript crShow: '2 secs']
] fork

您只需创建一个延迟对象,因为您希望每次迭代都延迟相同的时间。

如果您不需要索引值,则 timesRepeat: 更干净(如果您确实需要索引值,to:do: 比 whileTrue: 更干净)。

最后,如果您尝试通过向块发送值消息而不是分叉来进行调试,您将看到 10 秒延迟,然后将显示所有 5 行。这是因为在前台任务繁忙时 GUI 不会更新,而 fork 会导致块在后台运行并允许 GUI(特别是 Transcript)更新。

于 2012-12-02T06:47:20.490 回答
1
[5 timesRepeat: [
    (Delay forSeconds: 2) wait.
     Transcript crShow: '2 secs'] .
] fork
于 2012-12-14T22:59:36.177 回答