2017-04-08 27 views
1

我正在編寫一個包來控制使用Go的EDSDK DLL的Canon DSLR。在「LockOSThread」中調用函數GoRoutine

這是一個個人項目相片展臺,在我們的婚禮用在我的合作伙伴的要求,我會很高興地張貼在GitHub上完成時:)。

綜觀使用SDK的其他地方的例子,它不是線程安全的,並且使用線程本地資源,所以我需要確保我從一個單獨的線程使用過程中調用它。雖然這並不理想,但它看起來像Go提供了一個「runtime.LockOSThread」函數來實現這一點,雖然這確實被核心DLL互操作代碼本身調用,所以我將不得不等待並找出是否干擾。

我希望應用程序的其餘部分能夠使用更高級別的接口調用SDK而不用擔心線程,所以我需要一種方法將函數調用請求傳遞給鎖定的線程/ Goroutine以在那裏執行,然後將結果傳回給Goroutine之外的調用函數。

到目前爲止,我已經想出了使用非常廣泛的函數定義使用[]接口{}陣列和回傳,並通過渠道轉發的該工作示例。這會在每次調用時花費大量的輸入/輸出數據,以便從接口數組中返回類型斷言,即使我們知道我們應該提前爲每個函數預期什麼,但它看起來像它會工作。

之前,我投入了大量的時間做這種方式對可能做的最糟糕的方式 - 沒有任何人有任何更好的選擇?

package edsdk 

import (
    "fmt" 
    "runtime" 
) 

type CanonSDK struct { 
    FChan   chan functionCall 
} 

type functionCall struct { 
    Function  func([]interface{}) []interface{} 
    Arguments  []interface{} 
    Return   chan []interface{} 
} 

func NewCanonSDK() (*CanonSDK, error) { 
    c := &CanonSDK { 
     FChan: make(chan functionCall), 
    } 

    go c.BackgroundThread(c.FChan) 

    return c, nil 
} 

func (c *CanonSDK) BackgroundThread(fcalls <-chan functionCall) { 
    runtime.LockOSThread() 
    for f := range fcalls { 
     f.Return <- f.Function(f.Arguments) 
    } 
    runtime.UnlockOSThread() 
} 

func (c *CanonSDK) TestCall() { 
    ret := make(chan []interface{}) 

    f := functionCall { 
     Function: c.DoTestCall, 
     Arguments: []interface{}{}, 
     Return: ret, 
    } 

    c.FChan <- f 

    results := <- ret 
    close(ret) 

    fmt.Printf("%#v", results) 
} 

func (c *CanonSDK) DoTestCall([]interface{}) []interface{} { 
    return []interface{}{ "Test", nil } 
} 
+0

您的問題可能對於SO來說太複雜。嘗試將其歸結爲代碼中的單個關注點。 – eduncan911

回答

0

對於我已經玩過類似的嵌入式項目,我傾向於建立一個單一的goroutine工人監聽通道上超過該USB設備完成所有的工作。而任何結果都會在另一個頻道上發回。

與設備對話,與單向交流的渠道只有在圍棋。 LIsten來自其他渠道的回覆。

由於USB是串行和輪詢,我不得不建立一個專用通道與另一個goroutine,只是從通道中選擇項目,當它們從剛剛循環的工作程序中被推入時。