2017-04-08 25 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,只是从通道中选择项目,当它们从刚刚循环的工作程序中被推入时。