簡體   English   中英

Pharo承諾:

[英]Pharo promises:

我今年早些時候在Pharo Smalltalk開展了一項承諾項目。 我們的想法是實現以下行為:

([ 30 seconds wait. 4 ]promiseValue )then: [ :a| Transcript crShow: a ].

這意味着承諾將在后台等待30秒並在Transcript上打印。 這不應導致Pharo用戶界面凍結。 我在下面的實現凍結了用戶界面。 為什么?

實現Promises行為的類承諾:

Object subclass: #Promise
    instanceVariableNames: 'promiseValue promiseError promiseLock'
    classVariableNames: ''
    package: 'META-Project-[pgakuo]'

類Promise中的方法

doesNotUnderstand: aMessage 
    ^ self value 
        perform: aMessage selector
        withArguments: aMessage arguments

then: aBlock
    promiseLock isSignaled
        ifTrue: [ ^ self ].
    promiseLock wait.
    promiseError
        ifNotNil: [ promiseError
                privHandlerContext: thisContext;
                signal ].
    aBlock value: promiseValue.
    self value: aBlock

then: aBlock catch: anotherBlock
    promiseLock isSignaled
        ifFalse:
            [ promiseLock wait.
            promiseError ifNotNil: [ anotherBlock value: promiseError ].
            promiseValue ifNotNil: [  aBlock value: promiseValue. self value: aBlock  ]] 

value
    promiseLock  isSignaled ifFalse: [ promiseLock  wait ].
    promiseError  ifNotNil: 
        [ promiseError 
            privHandlerContext: thisContext;
            signal ].
    ^promiseValue 

value: aBlock 
    promiseLock := Semaphore new.
[
  [[promiseValue := aBlock value] 
    on: Error do: [:err | promiseError := err]]
    ensure: [promiseLock signal]] fork

並且一個方法添加到Blockclosure以使閉包使用Promise行為。

promiseValue
    ^ Promise  new value: self 

一個塊被傳遞給Promise的一個實例,它由Promise >> value執行:它使用fork在后台執行任務。 但它似乎沒有按預期工作

在游樂場工作時,您將在UI過程中工作。 因此,您實際上是使用您的示例暫停UI過程。 試試這個:

[ ([ 30 seconds wait. 4 ] promiseValue) then: [ :a |
    Transcript crShow: a ] ] forkAt: Processor userBackgroundPriority.

編輯

由於明確要求原始表達式不鎖定UI,您應該做的是:

  1. 不要覆蓋#doesNotUnderstand:
  2. 你有一個選擇:

    1. 在評估承諾時總是分叉

      由於進程調度和進程創建,這將產生開銷。 您還將丟失原始進程的上下文,除非您明確保存它(成本內存,導致性能損失)

    2. 如果當前進程是UI進程,則只進行fork

      檢查當前進程是否是UI進程非常簡單快速。 這不是你通常會做的事情,但對於你的情況,我會推薦這種方法。

  3. 我建議為Promise實現一個類側方法,例如Promise class>>value: . 這將允許您將此特定案例與其余實現隔離開來。 例如

     value: aBlock | instance | instance := self new. self isUIProcess ifTrue: [ [ instance value: aBlock ] forkAt: Processor userBackgroundPriority ] ifFalse: [ instance value: aBlock ]. ^ instance 

我解決了冰凍問題如下:

then: aBlock
    promiseLock isSignaled
        ifFalse:
            [ promiseLock wait.         
            promiseValue ifNotNil: [  aBlock value: promiseValue ]] fork. 

並且操場上的以下代碼不會凍結UI

[ 12 seconds wait. 12 ]promiseValue then: [ :a|  Transcript crShow: a/2 ] 

在沒有凍結UI的12秒后打印6

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM