在异步函数中包装非IO绑定的长时间运行的同步API

时间:2017-05-24 01:53:37

标签: c# asynchronous async-await interop

我有一个c ++ DLL,它将数据发送到USB设备并等待回复(可能长达10秒),此DLL没有构建回调。如果我从我的UI线程调用它,它显然会锁定UI。

我目前在C#中为这个C ++库编写了一个异步包装器来包装dll调用,例如

public async Task<USBResult> GetData(int command){

     //The real function has C#/C++ interop code to marshal the memory and free it.
     USBResult result;

     //This function most likely calls Thread.Sleep whilst it waits for a callback internally. 
     //I know it uses FTDIx.dll to do the USB calls.
     await Task.Run(() result = LongRunningDllCallWithNoCallback(command));

     return result;
}

我已经读过,不建议使用async over sync,但我认为在我的情况下没有其他方法可以实现此功能。我无法修改c ++ dll,开发人员也不会因为它符合15年前编写的SAE标准,因此如果更改将破坏其他应用程序。

这是不好的做法吗?如果是这样,那么在这个长时间运行的同步dll调用上创建异步函数的首选方法是什么?

1 个答案:

答案 0 :(得分:2)

  

我已经读过不建议使用async over sync,但我认为在我的情况下没有其他方法可以实现此功能。

正确,不推荐。

在你的情况下 - 你有一些不能异步的东西 - 你应该公开一个同步API,例如:

public USBResult GetData(int command) {
  // C#/C++ interop code to marshal the memory and free it.
  USBResult result;
  result = LongRunningDllCallWithNoCallback(command);
  return result;
}

然后,当从UI调用它的时候是正确的,那么使用await Task.Run调用,如下:

var response = await Task.Run(() => GetData(command));

有关此背后原因的详细信息,请参阅我的博文Task.Run in the implementation