[英]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,您應該做的是:
#doesNotUnderstand:
你有一個選擇:
在評估承諾時總是分叉
由於進程調度和進程創建,這將產生開銷。 您還將丟失原始進程的上下文,除非您明確保存它(成本內存,導致性能損失)
如果當前進程是UI進程,則只進行fork
檢查當前進程是否是UI進程非常簡單快速。 這不是你通常會做的事情,但對於你的情況,我會推薦這種方法。
我建議為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.