-
-
Notifications
You must be signed in to change notification settings - Fork 226
Add DeviceIoControlAsync helper method #504
Add DeviceIoControlAsync helper method #504
Conversation
It doesn't, actually. I pushed a commit to demonstrate. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will be a fine fit.
But I'd like to explore reducing memory pressure by using NativeOverlapped
(a struct) directly instead of the Overlapped
class. Also consider using ValueTask<uint>
instead of Task<uint>
.
public async Task DeviceIOControlAsync_Works() | ||
{ | ||
const uint FSCTL_SET_ZERO_DATA = 0x000980c8; | ||
string fileName = Path.Combine(Environment.CurrentDirectory, "test.txt"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't create files based on an assumption of the current directory, since xunit doesn't guarantee a particular current directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps create a file under the temp directory (and delete it later)?
The test (or other user code) no longer has to use `MemoryMarshal.Cast` .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix up the created file path, and promote your PR out of draft when you're ready to merge. :)
public async Task DeviceIOControlAsync_Works() | ||
{ | ||
const uint FSCTL_SET_ZERO_DATA = 0x000980c8; | ||
string fileName = Path.Combine(Environment.CurrentDirectory, "test.txt"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps create a file under the temp directory (and delete it later)?
Thanks, @AArnott . I rebased the PR, changed the I looked at replacing The implementation of Overlapped and NativeOverlapped look very specialized. I'm not sure whether that's because Net, if you want the further optimize this, I'll need some hints. Since it's an implementation detail (no changes to the public API), we could perhaps do that on a future PR. |
/// </summary> | ||
/// <param name="input"> | ||
/// The input buffer. | ||
/// </param> | ||
/// <param name="output"> | ||
/// The output buffer. | ||
/// </param> | ||
public DeviceIOControlOverlapped(Memory<byte> input, Memory<byte> output) | ||
internal DeviceIOControlOverlapped(Memory<TInput> input, Memory<TOutput> output) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, since this constructor (and the properties below) are defined on a class
which is private
to Kernel32
, is there any difference between marking it as public
or internal
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are subtle differences in Reflection, but the main reason is because public
triggers "public API review" mode in my mind as public APIs are very hard to change later, and these are in fact not public APIs. The C# public
keyword in private
or internal
types are in fact not public at all (unless they also implement an interface). So it's a misleading keyword to use, and makes code reviews more expensive. So I prefer internal
for members of non-public types instead of public
.
The use of the .NET |
This is a draft PR, to make the suggestion of #500 a bit more tangible. In this case, it adds an async wrapper around
DeviceIOControl
like this:The bulk of the 'glue' to convert a kernel method which returns
Win32ErrorCode.ERROR_IO_PENDING
to anasync
method is in theDeviceIOControlOverlapped
class. It ultimately registers a callback, which operates on aTaskCompletionSource
.In its current shape, the method task
Memory<byte>
rather thanvoid*
. The reason is C# doesn't let you mixunsafe
andasync
in the same method; so if you want to call this method in anasync
manner, have to avoidvoid*
.This does mean targeting
netstandard2.1
.