异步P/Invoke调用

Cla*_*sen 8 c#

我正在为机器人控制器创建一个包装库,它主要依赖于P/Invoke调用.

但是,机器人的许多功能(例如归位或移动)需要很长时间,并且在运行时执行线程锁定.

所以我想知道如何以异步方式包装功能,因此调用不会阻止我的UI线程.到目前为止我的想法是使用任务,但我不确定这是正确的方法.

public Task<bool> HomeAsync(Axis axis, CancellationToken token)
{
    return Task.Factory.StartNew(() => Home(axis), token);
}
Run Code Online (Sandbox Code Playgroud)

目前关于.NET中Async模型的大多数MSDN文章主要是在已经具有异步功能的库(例如File.BeginRead等)上进行转发.但我似乎无法找到有关如何实际编写异步功能的更多信息.

usr*_*ΛΩΝ 5

你有没有试过异步代表?我相信没有什么比它简单了.

如果您的线程阻塞方法是void Home(Axis)您首先定义委托类型,即.delegate void HomeDelegate(Axis ax),然后使用BeginInvokeHomeDelegate的新实例的方法指向Home方法的地址.

[DllImport[...]] //PInvoke
void Home(Axis x);

delegate void HomeDelegate(Axis x);

void main()
{
    HomeDelegate d = new HomeDelegate(Home);
    IAsyncResult ia = d.BeginInvoke(axis, null, null);
    [...]
    d.EndInvoke(ia);
}
Run Code Online (Sandbox Code Playgroud)

请记住,在某处使用EndInvoke(阻塞线程,直到方法最终结束,可能与IAsyncResult.Completed属性的轮询一起)对于检查您的异步任务是否真的已经完成非常有用.您可能不希望机器人打开它的手臂并留下玻璃杯,直到玻璃杯在桌子上方,你知道;-)

  • 而且您甚至不需要再定义委托类型.只需使用`Action <Axis>`. (2认同)

Cla*_*sen 5

经过一番讨论,我觉得这样的事情将成为黄金的中间道路.

public void HomeAsync(Axis axis, Action<bool> callback)
{
    Task.Factory
        .StartNew(() => Home(axis))
        .ContinueWith(task => callback(task.Result));
}
Run Code Online (Sandbox Code Playgroud)

我认为这是两全其美的.