【发布时间】:2015-10-26 18:53:15
【问题描述】:
我有一个 C 函数 FsReadStream,它执行一些异步工作并接受回调。完成后,它使用QueueUserWorkItem windows 函数调用回调。
我正在尝试使用 async/await 模式从托管代码 (c#) 调用此函数。所以我做了以下
- 构造一个
Task对象,向构造函数传递一个返回结果的lambda。 - 使用
RunSynchronously方法构造一个运行此任务的回调 - 调用异步原生函数,传入回调
- 将任务对象返回给调用者
我的代码看起来像这样
/// Reads into the buffer as many bytes as the buffer size
public Task<ReadResult> ReadAsync(byte[] buffer)
{
GCHandle pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr bytesToRead = Marshal.AllocHGlobal(sizeof(long));
Marshal.WriteInt64(bytesToRead, buffer.Length);
FsAsyncInfo asyncInfo = new FsAsyncInfo();
ReadResult readResult = new ReadResult();
Task<ReadResult> readCompletionTask = new Task<ReadResult>(() => { return readResult; });
TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
asyncInfo.Callback = (int status) =>
{
readResult.ErrorCode = status;
readResult.BytesRead = (int)Marshal.ReadInt64(bytesToRead);
readCompletionTask.RunSynchronously(scheduler);
pinnedBuffer.Free();
Marshal.FreeHGlobal(bytesToRead);
};
// Call asynchronous native method
NativeMethods.FsReadStream(
pinnedBuffer.AddrOfPinnedObject(),
bytesToRead,
ref asyncInfo);
return readCompletionTask;
}
我这样称呼它
ReadResult readResult = await ReadAsync(data);
我有两个问题
- 如何使调用
await ReadAsync后运行的代码与回调在同一线程上运行?目前,我看到它在不同的线程上运行,即使我正在调用readCompletionTask.RunSynchronously。我在 ASP.NET 和 IIS 下运行此代码。 - 本机
QueueUserWorkItem函数是否使用与托管ThreadPool.QueueUserWorkItem 方法相同的线程池?我的意见是应该这样做,因此托管TaskScheduler应该可以在本机回调线程上安排任务。
【问题讨论】:
标签: c# windows async-await pinvoke