打开主菜单

BOO入門/將函數當作物件與多執行緒

< BOO入門(重定向自BOO/將函數當作物件與多執行緒

BOO入門 > 將函數當作物件與多執行緒 (上一章:例外 下一章:Generators)


譯註:boo 裡的函數宣告好以後,就是一個物件了,你可以試著在 booish 裡使用 dir( your_function ) 看看。

將函數當作物件時,有三個有用的方法可用:

  1. function.Invoke(<arguments>) as <return type>
  2. function.BeginInvoke(<arguments>) as IAsyncResult
  3. function.EndInvoke(IAsyncResult) as <return type>

.Invoke 等同於呼叫函數本身,就像是:function()。 .BeginInvoke 會啟始一個單獨的執行緒來執行這個函數。 .EndInvoke 會完成之前啟始的函數並回傳適當的型別。

// .Invoke 的範例
def Nothing(x):
    return x

i = 5
print 5 == Nothing(i)
print i == Nothing.Invoke(i)
print i == Nothing.Invoke.Invoke(i)
// 譯註:原文使用 assert,這裡我改用 print 直接印出 boolean 值。使用 assert 時,後兩行執行時會出現 ERROR: 'bool' cannot be used in a boolean context.

你可以看到,.Invoke 就與呼叫函數一樣,甚至你還可以繼續把 .Invoke() 當作物件使用。

這裡有個 .BeginInvoke 的好例子:

//  .BeginInvoke 開始多執行緒
import System
import System.Threading

class FibonacciCalculator:
    def constructor():
        _alpha, _beta = 0, 1
        _stopped = true
    
    def Calculate():
        _stopped = false
        while not _stopped:
            Thread.Sleep(200)
            _alpha, _beta = _beta, _alpha + _beta
            print _beta
    
    def Start():
        _result = Calculate.BeginInvoke()
    
    def Stop():
        _stopped = true
        Calculate.EndInvoke(_result)

    _result as IAsyncResult
    
    _alpha as ulong
    _beta as ulong
    
    _stopped as bool

fib = FibonacciCalculator()
fib.Start()
prompt("按下 Enter 停止...\n")
fib.Stop()

輸出將會在每 200 毫秒(millisecond) 產生一個 Fibonacci數列,在超過 2^64 的時候,會發生一個溢出錯誤。(為甚麼是 200 毫秒?因為使用了 Thread.Sleep(200) ) 重要的是,當你按下 Enter 的時候,這個執行緒將會停止。

練習编辑

  1. 試著呼叫 .BeginInvoke 兩次看看,看看結果會如何?
  2. 跟 C# 比較看看,誰的方法比較方便?