mirror of https://github.com/dahall/Vanara.git
Completed unit tests and fixes for threadpoolapiset.h
parent
7746a986bf
commit
37c943fe4a
|
@ -13,40 +13,7 @@ namespace Vanara.PInvoke
|
||||||
/// <param name="ObjectContext">Optional application-defined data specified during creation of the object.</param>
|
/// <param name="ObjectContext">Optional application-defined data specified during creation of the object.</param>
|
||||||
/// <param name="CleanupContext">Optional application-defined data specified using CloseThreadpoolCleanupGroupMembers.</param>
|
/// <param name="CleanupContext">Optional application-defined data specified using CloseThreadpoolCleanupGroupMembers.</param>
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
public delegate void PTP_CLEANUP_GROUP_CANCEL_CALLBACK(IntPtr ObjectContext, IntPtr CleanupContext);
|
public delegate void CleanupGroupCancelCallback(IntPtr ObjectContext, IntPtr CleanupContext);
|
||||||
|
|
||||||
/// <summary>Applications implement this callback if they call the TrySubmitThreadpoolCallback function to start a worker thread.</summary>
|
|
||||||
/// <param name="Instance">
|
|
||||||
/// A TP_CALLBACK_INSTANCE structure that defines the callback instance. Applications do not modify the members of this structure.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="Context">The application-defined data.</param>
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
|
||||||
public delegate void PTP_SIMPLE_CALLBACK(PTP_CALLBACK_INSTANCE Instance, IntPtr Context);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Applications implement this callback if they call the SetThreadpoolTimer function to start a worker thread for the timer object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Instance">
|
|
||||||
/// A TP_CALLBACK_INSTANCE structure that defines the callback instance. Applications do not modify the members of this structure.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="Context">The application-defined data.</param>
|
|
||||||
/// <param name="Timer">A TP_TIMER structure that defines the timer object that generated the callback.</param>
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
|
||||||
public delegate void PTP_TIMER_CALLBACK(PTP_CALLBACK_INSTANCE Instance, IntPtr Context, PTP_TIMER Timer);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Applications implement this callback if they call the SetThreadpoolWait function to start a worker thread for the wait object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Instance">
|
|
||||||
/// A TP_CALLBACK_INSTANCE structure that defines the callback instance. Applications do not modify the members of this structure.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="Context">The application-defined data.</param>
|
|
||||||
/// <param name="Wait">A TP_WAIT structure that defines the wait object that generated the callback.</param>
|
|
||||||
/// <param name="WaitResult">
|
|
||||||
/// The result of the wait operation. This parameter can be one of the following values from WaitForMultipleObjects: WAIT_OBJECT_0, WAIT_TIMEOUT
|
|
||||||
/// </param>
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
|
||||||
public delegate void PTP_WAIT_CALLBACK(PTP_CALLBACK_INSTANCE Instance, IntPtr Context, PTP_WAIT Wait, uint WaitResult);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applications implement this callback if they call the StartThreadpoolIo function to start a worker thread for the I/O completion object.
|
/// Applications implement this callback if they call the StartThreadpoolIo function to start a worker thread for the I/O completion object.
|
||||||
|
@ -66,9 +33,42 @@ namespace Vanara.PInvoke
|
||||||
/// <param name="NumberOfBytesTransferred">The number of bytes transferred during the I/O operation that has completed.</param>
|
/// <param name="NumberOfBytesTransferred">The number of bytes transferred during the I/O operation that has completed.</param>
|
||||||
/// <param name="Io">A TP_IO structure that defines the I/O completion object that generated the callback.</param>
|
/// <param name="Io">A TP_IO structure that defines the I/O completion object that generated the callback.</param>
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
public delegate void PTP_WIN32_IO_CALLBACK(PTP_CALLBACK_INSTANCE Instance, IntPtr Context, IntPtr Overlapped, uint IoResult,
|
public delegate void IoCompletionCallback(PTP_CALLBACK_INSTANCE Instance, IntPtr Context, IntPtr Overlapped, uint IoResult,
|
||||||
UIntPtr NumberOfBytesTransferred, PTP_IO Io);
|
UIntPtr NumberOfBytesTransferred, PTP_IO Io);
|
||||||
|
|
||||||
|
/// <summary>Applications implement this callback if they call the TrySubmitThreadpoolCallback function to start a worker thread.</summary>
|
||||||
|
/// <param name="Instance">
|
||||||
|
/// A TP_CALLBACK_INSTANCE structure that defines the callback instance. Applications do not modify the members of this structure.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Context">The application-defined data.</param>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
public delegate void SimpleCallback(PTP_CALLBACK_INSTANCE Instance, IntPtr Context);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applications implement this callback if they call the SetThreadpoolTimer function to start a worker thread for the timer object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Instance">
|
||||||
|
/// A TP_CALLBACK_INSTANCE structure that defines the callback instance. Applications do not modify the members of this structure.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Context">The application-defined data.</param>
|
||||||
|
/// <param name="Timer">A TP_TIMER structure that defines the timer object that generated the callback.</param>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
public delegate void TimerCallback(PTP_CALLBACK_INSTANCE Instance, IntPtr Context, PTP_TIMER Timer);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applications implement this callback if they call the SetThreadpoolWait function to start a worker thread for the wait object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Instance">
|
||||||
|
/// A TP_CALLBACK_INSTANCE structure that defines the callback instance. Applications do not modify the members of this structure.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="Context">The application-defined data.</param>
|
||||||
|
/// <param name="Wait">A TP_WAIT structure that defines the wait object that generated the callback.</param>
|
||||||
|
/// <param name="WaitResult">
|
||||||
|
/// The result of the wait operation. This parameter can be one of the following values from WaitForMultipleObjects: WAIT_OBJECT_0, WAIT_TIMEOUT
|
||||||
|
/// </param>
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
|
public delegate void WaitCallback(PTP_CALLBACK_INSTANCE Instance, IntPtr Context, PTP_WAIT Wait, uint WaitResult);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applications implement this callback if they call the SubmitThreadpoolWork function to start a worker thread for the work object.
|
/// Applications implement this callback if they call the SubmitThreadpoolWork function to start a worker thread for the work object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -78,7 +78,7 @@ namespace Vanara.PInvoke
|
||||||
/// <param name="Context">The application-defined data.</param>
|
/// <param name="Context">The application-defined data.</param>
|
||||||
/// <param name="Work">A TP_WORK structure that defines the work object that generated the callback.</param>
|
/// <param name="Work">A TP_WORK structure that defines the work object that generated the callback.</param>
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||||
public delegate void PTP_WORK_CALLBACK(PTP_CALLBACK_INSTANCE Instance, IntPtr Context, PTP_WORK Work);
|
public delegate void WorkCallback(PTP_CALLBACK_INSTANCE Instance, IntPtr Context, PTP_WORK Work);
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum TP_CALLBACK_ENV_FLAGS
|
public enum TP_CALLBACK_ENV_FLAGS
|
||||||
|
@ -175,7 +175,7 @@ namespace Vanara.PInvoke
|
||||||
// PVOID pvCleanupContext); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682036(v=vs.85).aspx
|
// PVOID pvCleanupContext); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682036(v=vs.85).aspx
|
||||||
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms682036")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms682036")]
|
||||||
public static extern void CloseThreadpoolCleanupGroupMembers(PTP_CLEANUP_GROUP ptpcg, [MarshalAs(UnmanagedType.Bool)] bool fCancelPendingCallbacks, IntPtr pvCleanupContext);
|
public static extern void CloseThreadpoolCleanupGroupMembers(PTP_CLEANUP_GROUP ptpcg, [MarshalAs(UnmanagedType.Bool)] bool fCancelPendingCallbacks, [Optional] IntPtr pvCleanupContext);
|
||||||
|
|
||||||
/// <summary>Releases the specified I/O completion object.</summary>
|
/// <summary>Releases the specified I/O completion object.</summary>
|
||||||
/// <param name="pio">
|
/// <param name="pio">
|
||||||
|
@ -224,12 +224,28 @@ namespace Vanara.PInvoke
|
||||||
/// If the function succeeds, it returns a <c>TP_POOL</c> structure representing the newly allocated thread pool. Applications do not
|
/// If the function succeeds, it returns a <c>TP_POOL</c> structure representing the newly allocated thread pool. Applications do not
|
||||||
/// modify the members of this structure.
|
/// modify the members of this structure.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>If function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
/// <para>If function fails, it returns NULL. To retrieve extended error information, call GetLastError.</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// PTP_POOL WINAPI CreateThreadpool( _Reserved_ PVOID reserved); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682456(v=vs.85).aspx
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// After creating the new thread pool, you should call SetThreadpoolThreadMaximum to specify the maximum number of threads that the
|
||||||
|
/// pool can allocate and SetThreadpoolThreadMinimum to specify the minimum number of threads available in the pool.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// To use the pool, you must associate the pool with a callback environment. To create the callback environment, call
|
||||||
|
/// InitializeThreadpoolEnvironment. Then, call SetThreadpoolCallbackPool to associate the pool with the callback environment.
|
||||||
|
/// </para>
|
||||||
|
/// <para>To release the thread pool, call CloseThreadpool.</para>
|
||||||
|
/// <para>To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or higher.</para>
|
||||||
|
/// <para>Examples</para>
|
||||||
|
/// <para>For an example, see Using the Thread Pool Functions.</para>
|
||||||
|
/// </remarks>
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/api/threadpoolapiset/nf-threadpoolapiset-createthreadpool PTP_POOL
|
||||||
|
// CreateThreadpool( PVOID reserved );
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms682456")]
|
[PInvokeData("threadpoolapiset.h", MSDNShortId = "cc00d7bf-ac52-44ff-a6a8-76c8eaace5e6")]
|
||||||
public static extern PTP_POOL CreateThreadpool(IntPtr reserved = default);
|
// public static extern PTP_POOL CreateThreadpool(IntPtr reserved);
|
||||||
|
public static extern SafePTP_POOL CreateThreadpool(IntPtr reserved = default);
|
||||||
|
|
||||||
/// <summary>Creates a cleanup group that applications can use to track one or more thread pool callbacks.</summary>
|
/// <summary>Creates a cleanup group that applications can use to track one or more thread pool callbacks.</summary>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
|
@ -242,7 +258,7 @@ namespace Vanara.PInvoke
|
||||||
// PTP_CLEANUP_GROUP WINAPI CreateThreadpoolCleanupGroup(void); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682462(v=vs.85).aspx
|
// PTP_CLEANUP_GROUP WINAPI CreateThreadpoolCleanupGroup(void); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682462(v=vs.85).aspx
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms682462")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms682462")]
|
||||||
public static extern PTP_CLEANUP_GROUP CreateThreadpoolCleanupGroup();
|
public static extern SafePTP_CLEANUP_GROUP CreateThreadpoolCleanupGroup();
|
||||||
|
|
||||||
/// <summary>Creates a new I/O completion object.</summary>
|
/// <summary>Creates a new I/O completion object.</summary>
|
||||||
/// <param name="fl">The file handle to bind to this I/O completion object.</param>
|
/// <param name="fl">The file handle to bind to this I/O completion object.</param>
|
||||||
|
@ -264,11 +280,11 @@ namespace Vanara.PInvoke
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// PTP_IO WINAPI CreateThreadpoolIo( _In_ HANDLE fl, _In_ PTP_WIN32_IO_CALLBACK pfnio, _Inout_opt_ PVOID pv, _In_opt_
|
// PTP_IO WINAPI CreateThreadpoolIo( _In_ HANDLE fl, _In_ IoCompletionCallback pfnio, _Inout_opt_ PVOID pv, _In_opt_
|
||||||
// PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682464(v=vs.85).aspx
|
// PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682464(v=vs.85).aspx
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms682464")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms682464")]
|
||||||
public static extern PTP_IO CreateThreadpoolIo(HFILE fl, PTP_WIN32_IO_CALLBACK pfnio, IntPtr pv, PTP_CALLBACK_ENVIRON pcbe);
|
public static extern SafePTP_IO CreateThreadpoolIo(HFILE fl, IoCompletionCallback pfnio, IntPtr pv, PTP_CALLBACK_ENVIRON pcbe);
|
||||||
|
|
||||||
/// <summary>Creates a new timer object.</summary>
|
/// <summary>Creates a new timer object.</summary>
|
||||||
/// <param name="pfnti">The callback function to call each time the timer object expires. For details, see <c>TimerCallback</c>.</param>
|
/// <param name="pfnti">The callback function to call each time the timer object expires. For details, see <c>TimerCallback</c>.</param>
|
||||||
|
@ -287,10 +303,10 @@ namespace Vanara.PInvoke
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// PTP_TIMER WINAPI CreateThreadpoolTimer( _In_ PTP_TIMER_CALLBACK pfnti, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682466(v=vs.85).aspx
|
// PTP_TIMER WINAPI CreateThreadpoolTimer( _In_ TimerCallback pfnti, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682466(v=vs.85).aspx
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms682466")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms682466")]
|
||||||
public static extern PTP_TIMER CreateThreadpoolTimer(PTP_TIMER_CALLBACK pfnti, IntPtr pv, PTP_CALLBACK_ENVIRON pcbe);
|
public static extern SafePTP_TIMER CreateThreadpoolTimer(TimerCallback pfnti, [Optional] IntPtr pv, [Optional] PTP_CALLBACK_ENVIRON pcbe);
|
||||||
|
|
||||||
/// <summary>Creates a new wait object.</summary>
|
/// <summary>Creates a new wait object.</summary>
|
||||||
/// <param name="pfnwa">The callback function to call when the wait completes or times out. For details, see <c>WaitCallback</c>.</param>
|
/// <param name="pfnwa">The callback function to call when the wait completes or times out. For details, see <c>WaitCallback</c>.</param>
|
||||||
|
@ -309,10 +325,10 @@ namespace Vanara.PInvoke
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// PTP_WAIT WINAPI CreateThreadpoolWait( _In_ PTP_WAIT_CALLBACK pfnwa, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682474(v=vs.85).aspx
|
// PTP_WAIT WINAPI CreateThreadpoolWait( _In_ WaitCallback pfnwa, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682474(v=vs.85).aspx
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms682474")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms682474")]
|
||||||
public static extern PTP_WAIT CreateThreadpoolWait(PTP_WAIT_CALLBACK pfnwa, IntPtr pv, PTP_CALLBACK_ENVIRON pcbe);
|
public static extern SafePTP_WAIT CreateThreadpoolWait(WaitCallback pfnwa, [Optional] IntPtr pv, [Optional] PTP_CALLBACK_ENVIRON pcbe);
|
||||||
|
|
||||||
/// <summary>Creates a new work object.</summary>
|
/// <summary>Creates a new work object.</summary>
|
||||||
/// <param name="pfnwk">
|
/// <param name="pfnwk">
|
||||||
|
@ -334,10 +350,10 @@ namespace Vanara.PInvoke
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// PTP_WORK WINAPI CreateThreadpoolWork( _In_ PTP_WORK_CALLBACK pfnwk, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682478(v=vs.85).aspx
|
// PTP_WORK WINAPI CreateThreadpoolWork( _In_ WorkCallback pfnwk, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682478(v=vs.85).aspx
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms682478")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms682478")]
|
||||||
public static extern PTP_WORK CreateThreadpoolWork(PTP_WORK_CALLBACK pfnwk, IntPtr pv, PTP_CALLBACK_ENVIRON pcbe);
|
public static extern SafePTP_WORK CreateThreadpoolWork(WorkCallback pfnwk, [Optional] IntPtr pv, [Optional] PTP_CALLBACK_ENVIRON pcbe);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes the association between the currently executing callback function and the object that initiated the callback. The current
|
/// Removes the association between the currently executing callback function and the object that initiated the callback. The current
|
||||||
|
@ -457,7 +473,7 @@ namespace Vanara.PInvoke
|
||||||
// VOID SetThreadpoolCallbackCleanupGroup( _Inout_ PTP_CALLBACK_ENVIRON pcbe, _In_ PTP_CLEANUP_GROUP ptpcg, _In_opt_
|
// VOID SetThreadpoolCallbackCleanupGroup( _Inout_ PTP_CALLBACK_ENVIRON pcbe, _In_ PTP_CLEANUP_GROUP ptpcg, _In_opt_
|
||||||
// PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng); https://msdn.microsoft.com/en-us/library/windows/desktop/ms686255(v=vs.85).aspx
|
// PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng); https://msdn.microsoft.com/en-us/library/windows/desktop/ms686255(v=vs.85).aspx
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms686255")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms686255")]
|
||||||
public static void SetThreadpoolCallbackCleanupGroup(this PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, PTP_CLEANUP_GROUP_CANCEL_CALLBACK pfng)
|
public static void SetThreadpoolCallbackCleanupGroup(this PTP_CALLBACK_ENVIRON pcbe, PTP_CLEANUP_GROUP ptpcg, [Optional] CleanupGroupCancelCallback pfng)
|
||||||
{
|
{
|
||||||
pcbe.CleanupGroup = ptpcg;
|
pcbe.CleanupGroup = ptpcg;
|
||||||
pcbe.CleanupGroupCancelCallback = pfng;
|
pcbe.CleanupGroupCancelCallback = pfng;
|
||||||
|
@ -621,7 +637,7 @@ namespace Vanara.PInvoke
|
||||||
// msWindowLength); https://msdn.microsoft.com/en-us/library/windows/desktop/ms686271(v=vs.85).aspx
|
// msWindowLength); https://msdn.microsoft.com/en-us/library/windows/desktop/ms686271(v=vs.85).aspx
|
||||||
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms686271")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms686271")]
|
||||||
public static extern void SetThreadpoolTimer(PTP_TIMER pti, in FILETIME pftDueTime, uint msPeriod, uint msWindowLength);
|
public static extern void SetThreadpoolTimer(PTP_TIMER pti, in FILETIME pftDueTime, [Optional] uint msPeriod, [Optional] uint msWindowLength);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the timer object—, replacing the previous timer, if any. A worker thread calls the timer object's callback after the
|
/// Sets the timer object—, replacing the previous timer, if any. A worker thread calls the timer object's callback after the
|
||||||
|
@ -659,7 +675,7 @@ namespace Vanara.PInvoke
|
||||||
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
|
||||||
[PInvokeData("Threadpoolapiset.h", MSDNShortId = "dn894018")]
|
[PInvokeData("Threadpoolapiset.h", MSDNShortId = "dn894018")]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
public static extern bool SetThreadpoolTimerEx(PTP_TIMER pti, in FILETIME pftDueTime, uint msPeriod, uint msWindowLength);
|
public static extern bool SetThreadpoolTimerEx(PTP_TIMER pti, in FILETIME pftDueTime, [Optional] uint msPeriod, [Optional] uint msWindowLength);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the wait object—replacing the previous wait object, if any. A worker thread calls the wait object's callback function after
|
/// Sets the wait object—replacing the previous wait object, if any. A worker thread calls the wait object's callback function after
|
||||||
|
@ -694,6 +710,72 @@ namespace Vanara.PInvoke
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms686273")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms686273")]
|
||||||
public static extern void SetThreadpoolWait(PTP_WAIT pwa, SafeEventHandle h, in FILETIME pftTimeout);
|
public static extern void SetThreadpoolWait(PTP_WAIT pwa, SafeEventHandle h, in FILETIME pftTimeout);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the wait object—replacing the previous wait object, if any. A worker thread calls the wait object's callback function after
|
||||||
|
/// the handle becomes signaled or after the specified timeout expires.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pwa">
|
||||||
|
/// A pointer to a <c>TP_WAIT</c> structure that defines the wait object. The <c>CreateThreadpoolWait</c> function returns this structure.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="h">
|
||||||
|
/// <para>A handle.</para>
|
||||||
|
/// <para>
|
||||||
|
/// If this parameter is NULL, the wait object will cease to queue new callbacks (but callbacks already queued will still occur).
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter is not NULL, it must refer to a valid waitable object.</para>
|
||||||
|
/// <para>
|
||||||
|
/// If this handle is closed while the wait is still pending, the function's behavior is undefined. If the wait is still pending and
|
||||||
|
/// the handle must be closed, use <c>CloseThreadpoolWait</c> to cancel the wait and then close the handle.
|
||||||
|
/// </para>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="pftTimeout">
|
||||||
|
/// <para>
|
||||||
|
/// A pointer to a <c>FILETIME</c> structure that specifies the absolute or relative time at which the wait operation should time
|
||||||
|
/// out. If this parameter points to a positive value, it indicates the absolute time since January 1, 1601 (UTC), in 100-nanosecond
|
||||||
|
/// intervals. If this parameter points to a negative value, it indicates the amount of time to wait relative to the current time.
|
||||||
|
/// For more information about time values, see File Times.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter points to 0, the wait times out immediately. If this parameter is NULL, the wait will not time out.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>This function does not return a value.</returns>
|
||||||
|
// VOID WINAPI SetThreadpoolWait( _Inout_ PTP_WAIT pwa, _In_opt_ HANDLE h, _In_opt_ PFILETIME pftTimeout); https://msdn.microsoft.com/en-us/library/windows/desktop/ms686273(v=vs.85).aspx
|
||||||
|
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
|
||||||
|
[PInvokeData("WinBase.h", MSDNShortId = "ms686273")]
|
||||||
|
public static extern void SetThreadpoolWait(PTP_WAIT pwa, SafeEventHandle h, [Optional] IntPtr pftTimeout);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the wait object—replacing the previous wait object, if any. A worker thread calls the wait object's callback function after
|
||||||
|
/// the handle becomes signaled or after the specified timeout expires.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pwa">
|
||||||
|
/// A pointer to a <c>TP_WAIT</c> structure that defines the wait object. The <c>CreateThreadpoolWait</c> function returns this structure.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="h">
|
||||||
|
/// <para>A handle.</para>
|
||||||
|
/// <para>
|
||||||
|
/// If this parameter is NULL, the wait object will cease to queue new callbacks (but callbacks already queued will still occur).
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter is not NULL, it must refer to a valid waitable object.</para>
|
||||||
|
/// <para>
|
||||||
|
/// If this handle is closed while the wait is still pending, the function's behavior is undefined. If the wait is still pending and
|
||||||
|
/// the handle must be closed, use <c>CloseThreadpoolWait</c> to cancel the wait and then close the handle.
|
||||||
|
/// </para>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="pftTimeout">
|
||||||
|
/// <para>
|
||||||
|
/// A pointer to a <c>FILETIME</c> structure that specifies the absolute or relative time at which the wait operation should time
|
||||||
|
/// out. If this parameter points to a positive value, it indicates the absolute time since January 1, 1601 (UTC), in 100-nanosecond
|
||||||
|
/// intervals. If this parameter points to a negative value, it indicates the amount of time to wait relative to the current time.
|
||||||
|
/// For more information about time values, see File Times.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter points to 0, the wait times out immediately. If this parameter is NULL, the wait will not time out.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>This function does not return a value.</returns>
|
||||||
|
// VOID WINAPI SetThreadpoolWait( _Inout_ PTP_WAIT pwa, _In_opt_ HANDLE h, _In_opt_ PFILETIME pftTimeout); https://msdn.microsoft.com/en-us/library/windows/desktop/ms686273(v=vs.85).aspx
|
||||||
|
[DllImport(Lib.Kernel32, SetLastError = false, ExactSpelling = true)]
|
||||||
|
[PInvokeData("WinBase.h", MSDNShortId = "ms686273")]
|
||||||
|
public static extern void SetThreadpoolWait(PTP_WAIT pwa, [Optional] IntPtr h, [Optional] IntPtr pftTimeout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the wait object—replacing the previous wait object, if any. A worker thread calls the wait object's callback function after
|
/// Sets the wait object—replacing the previous wait object, if any. A worker thread calls the wait object's callback function after
|
||||||
/// the handle becomes signaled or after the specified timeout expires.
|
/// the handle becomes signaled or after the specified timeout expires.
|
||||||
|
@ -770,11 +852,11 @@ namespace Vanara.PInvoke
|
||||||
/// <para>If the function succeeds, it returns TRUE.</para>
|
/// <para>If the function succeeds, it returns TRUE.</para>
|
||||||
/// <para>If the function fails, it returns FALSE. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
/// <para>If the function fails, it returns FALSE. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
/// </returns>
|
/// </returns>
|
||||||
// BOOL WINAPI TrySubmitThreadpoolCallback( _In_ PTP_SIMPLE_CALLBACK pfns, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms686862(v=vs.85).aspx
|
// BOOL WINAPI TrySubmitThreadpoolCallback( _In_ SimpleCallback pfns, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms686862(v=vs.85).aspx
|
||||||
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms686862")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms686862")]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
public static extern bool TrySubmitThreadpoolCallback(PTP_SIMPLE_CALLBACK pfns, IntPtr pv, PTP_CALLBACK_ENVIRON pcbe);
|
public static extern bool TrySubmitThreadpoolCallback(SimpleCallback pfns, [Optional] IntPtr pv, [Optional] PTP_CALLBACK_ENVIRON pcbe);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waits for outstanding I/O completion callbacks to complete and optionally cancels pending callbacks that have not yet started to execute.
|
/// Waits for outstanding I/O completion callbacks to complete and optionally cancels pending callbacks that have not yet started to execute.
|
||||||
|
@ -828,46 +910,367 @@ namespace Vanara.PInvoke
|
||||||
[PInvokeData("WinBase.h", MSDNShortId = "ms687053")]
|
[PInvokeData("WinBase.h", MSDNShortId = "ms687053")]
|
||||||
public static extern void WaitForThreadpoolWorkCallbacks(PTP_WORK pwk, [MarshalAs(UnmanagedType.Bool)] bool fCancelPendingCallbacks);
|
public static extern void WaitForThreadpoolWorkCallbacks(PTP_WORK pwk, [MarshalAs(UnmanagedType.Bool)] bool fCancelPendingCallbacks);
|
||||||
|
|
||||||
|
/// <summary>Creates a new timer object.</summary>
|
||||||
|
/// <param name="pfnti">The callback function to call each time the timer object expires. For details, see <c>TimerCallback</c>.</param>
|
||||||
|
/// <param name="pv">Optional application-defined data to pass to the callback function.</param>
|
||||||
|
/// <param name="pcbe">
|
||||||
|
/// <para>
|
||||||
|
/// A <c>TP_CALLBACK_ENVIRON</c> structure that defines the environment in which to execute the callback. The
|
||||||
|
/// <c>InitializeThreadpoolEnvironment</c> function returns this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter is NULL, the callback executes in the default callback environment. For more information, see <c>InitializeThreadpoolEnvironment</c>.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// <para>
|
||||||
|
/// If the function succeeds, it returns a <c>TP_TIMER</c> structure that defines the timer object. Applications do not modify the
|
||||||
|
/// members of this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
|
/// </returns>
|
||||||
|
// PTP_TIMER WINAPI CreateThreadpoolTimer( _In_ TimerCallback pfnti, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682466(v=vs.85).aspx
|
||||||
|
[DllImport(Lib.Kernel32, SetLastError = true, EntryPoint = "CreateThreadpoolTimer")]
|
||||||
|
[PInvokeData("WinBase.h", MSDNShortId = "ms682466")]
|
||||||
|
internal static extern PTP_TIMER InternalCreateThreadpoolTimer(TimerCallback pfnti, IntPtr pv, PTP_CALLBACK_ENVIRON pcbe);
|
||||||
|
|
||||||
|
/// <summary>Creates a new wait object.</summary>
|
||||||
|
/// <param name="pfnwa">The callback function to call when the wait completes or times out. For details, see <c>WaitCallback</c>.</param>
|
||||||
|
/// <param name="pv">Optional application-defined data to pass to the callback function.</param>
|
||||||
|
/// <param name="pcbe">
|
||||||
|
/// <para>
|
||||||
|
/// A <c>TP_CALLBACK_ENVIRON</c> structure that defines the environment in which to execute the callback. The
|
||||||
|
/// <c>InitializeThreadpoolEnvironment</c> function returns this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter is NULL, the callback executes in the default callback environment. For more information, see <c>InitializeThreadpoolEnvironment</c>.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// <para>
|
||||||
|
/// If the function succeeds, it returns a <c>TP_WAIT</c> structure that defines the wait object. Applications do not modify the
|
||||||
|
/// members of this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
|
/// </returns>
|
||||||
|
// PTP_WAIT WINAPI CreateThreadpoolWait( _In_ WaitCallback pfnwa, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682474(v=vs.85).aspx
|
||||||
|
[DllImport(Lib.Kernel32, SetLastError = true, EntryPoint = "CreateThreadpoolWait")]
|
||||||
|
[PInvokeData("WinBase.h", MSDNShortId = "ms682474")]
|
||||||
|
internal static extern PTP_WAIT InternalCreateThreadpoolWait(WaitCallback pfnwa, IntPtr pv, PTP_CALLBACK_ENVIRON pcbe);
|
||||||
|
|
||||||
|
/// <summary>Creates a new work object.</summary>
|
||||||
|
/// <param name="pfnwk">
|
||||||
|
/// The callback function. A worker thread calls this callback each time you call <c>SubmitThreadpoolWork</c> to post the work
|
||||||
|
/// object. For details, see <c>WorkCallback</c>.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="pv">Optional application-defined data to pass to the callback function.</param>
|
||||||
|
/// <param name="pcbe">
|
||||||
|
/// <para>
|
||||||
|
/// A <c>TP_CALLBACK_ENVIRON</c> structure that defines the environment in which to execute the callback. The
|
||||||
|
/// <c>InitializeThreadpoolEnvironment</c> function returns this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter is NULL, the callback executes in the default callback environment. For more information, see <c>InitializeThreadpoolEnvironment</c>.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// <para>
|
||||||
|
/// If the function succeeds, it returns a <c>TP_WORK</c> structure that defines the work object. Applications do not modify the
|
||||||
|
/// members of this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
|
/// </returns>
|
||||||
|
// PTP_WORK WINAPI CreateThreadpoolWork( _In_ WorkCallback pfnwk, _Inout_opt_ PVOID pv, _In_opt_ PTP_CALLBACK_ENVIRON pcbe); https://msdn.microsoft.com/en-us/library/windows/desktop/ms682478(v=vs.85).aspx
|
||||||
|
[DllImport(Lib.Kernel32, SetLastError = true, EntryPoint = "CreateThreadpoolWork")]
|
||||||
|
[PInvokeData("WinBase.h", MSDNShortId = "ms682478")]
|
||||||
|
internal static extern PTP_WORK InternalCreateThreadpoolWork(WorkCallback pfnwk, IntPtr pv, PTP_CALLBACK_ENVIRON pcbe);
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct PTP_CALLBACK_INSTANCE
|
public struct PTP_CALLBACK_INSTANCE
|
||||||
{
|
{
|
||||||
private readonly IntPtr handle;
|
private readonly IntPtr handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a handle to a pool cleanup group.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct PTP_CLEANUP_GROUP
|
public struct PTP_CLEANUP_GROUP : IHandle
|
||||||
{
|
{
|
||||||
private readonly IntPtr handle;
|
private IntPtr handle;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="PTP_CLEANUP_GROUP"/> struct.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
public PTP_CLEANUP_GROUP(IntPtr preexistingHandle) => handle = preexistingHandle;
|
||||||
|
|
||||||
|
/// <summary>Returns an invalid handle by instantiating a <see cref="PTP_CLEANUP_GROUP"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
||||||
|
public static PTP_CLEANUP_GROUP NULL => new PTP_CLEANUP_GROUP(IntPtr.Zero);
|
||||||
|
|
||||||
|
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
||||||
|
public bool IsNull => handle == IntPtr.Zero;
|
||||||
|
|
||||||
|
/// <summary>Performs an explicit conversion from <see cref="PTP_CLEANUP_GROUP"/> to <see cref="IntPtr"/>.</summary>
|
||||||
|
/// <param name="h">The handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static explicit operator IntPtr(PTP_CLEANUP_GROUP h) => h.handle;
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="PTP_CLEANUP_GROUP"/>.</summary>
|
||||||
|
/// <param name="h">The pointer to a handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_CLEANUP_GROUP(IntPtr h) => new PTP_CLEANUP_GROUP(h);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator !=.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator !=(PTP_CLEANUP_GROUP h1, PTP_CLEANUP_GROUP h2) => !(h1 == h2);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator ==.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator ==(PTP_CLEANUP_GROUP h1, PTP_CLEANUP_GROUP h2) => h1.Equals(h2);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals(object obj) => obj is PTP_CLEANUP_GROUP h ? handle == h.handle : false;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode() => handle.GetHashCode();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IntPtr DangerousGetHandle() => handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a handle to a threadpool IO.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct PTP_IO
|
public struct PTP_IO : IHandle
|
||||||
{
|
{
|
||||||
private readonly IntPtr handle;
|
private IntPtr handle;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="PTP_IO"/> struct.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
public PTP_IO(IntPtr preexistingHandle) => handle = preexistingHandle;
|
||||||
|
|
||||||
|
/// <summary>Returns an invalid handle by instantiating a <see cref="PTP_IO"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
||||||
|
public static PTP_IO NULL => new PTP_IO(IntPtr.Zero);
|
||||||
|
|
||||||
|
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
||||||
|
public bool IsNull => handle == IntPtr.Zero;
|
||||||
|
|
||||||
|
/// <summary>Performs an explicit conversion from <see cref="PTP_IO"/> to <see cref="IntPtr"/>.</summary>
|
||||||
|
/// <param name="h">The handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static explicit operator IntPtr(PTP_IO h) => h.handle;
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="PTP_IO"/>.</summary>
|
||||||
|
/// <param name="h">The pointer to a handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_IO(IntPtr h) => new PTP_IO(h);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator !=.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator !=(PTP_IO h1, PTP_IO h2) => !(h1 == h2);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator ==.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator ==(PTP_IO h1, PTP_IO h2) => h1.Equals(h2);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals(object obj) => obj is PTP_IO h ? handle == h.handle : false;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode() => handle.GetHashCode();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IntPtr DangerousGetHandle() => handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a handle to a thread pool.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct PTP_POOL
|
public struct PTP_POOL : IHandle
|
||||||
{
|
{
|
||||||
private readonly IntPtr handle;
|
private IntPtr handle;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="PTP_POOL"/> struct.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
public PTP_POOL(IntPtr preexistingHandle) => handle = preexistingHandle;
|
||||||
|
|
||||||
|
/// <summary>Returns an invalid handle by instantiating a <see cref="PTP_POOL"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
||||||
|
public static PTP_POOL NULL => new PTP_POOL(IntPtr.Zero);
|
||||||
|
|
||||||
|
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
||||||
|
public bool IsNull => handle == IntPtr.Zero;
|
||||||
|
|
||||||
|
/// <summary>Performs an explicit conversion from <see cref="PTP_POOL"/> to <see cref="IntPtr"/>.</summary>
|
||||||
|
/// <param name="h">The handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static explicit operator IntPtr(PTP_POOL h) => h.handle;
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="PTP_POOL"/>.</summary>
|
||||||
|
/// <param name="h">The pointer to a handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_POOL(IntPtr h) => new PTP_POOL(h);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator !=.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator !=(PTP_POOL h1, PTP_POOL h2) => !(h1 == h2);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator ==.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator ==(PTP_POOL h1, PTP_POOL h2) => h1.Equals(h2);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals(object obj) => obj is PTP_POOL h ? handle == h.handle : false;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode() => handle.GetHashCode();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IntPtr DangerousGetHandle() => handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a handle to a threadpool timer.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct PTP_TIMER
|
public struct PTP_TIMER : IHandle
|
||||||
{
|
{
|
||||||
private readonly IntPtr handle;
|
private IntPtr handle;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="PTP_TIMER"/> struct.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
public PTP_TIMER(IntPtr preexistingHandle) => handle = preexistingHandle;
|
||||||
|
|
||||||
|
/// <summary>Returns an invalid handle by instantiating a <see cref="PTP_TIMER"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
||||||
|
public static PTP_TIMER NULL => new PTP_TIMER(IntPtr.Zero);
|
||||||
|
|
||||||
|
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
||||||
|
public bool IsNull => handle == IntPtr.Zero;
|
||||||
|
|
||||||
|
/// <summary>Performs an explicit conversion from <see cref="PTP_TIMER"/> to <see cref="IntPtr"/>.</summary>
|
||||||
|
/// <param name="h">The handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static explicit operator IntPtr(PTP_TIMER h) => h.handle;
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="PTP_TIMER"/>.</summary>
|
||||||
|
/// <param name="h">The pointer to a handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_TIMER(IntPtr h) => new PTP_TIMER(h);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator !=.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator !=(PTP_TIMER h1, PTP_TIMER h2) => !(h1 == h2);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator ==.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator ==(PTP_TIMER h1, PTP_TIMER h2) => h1.Equals(h2);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals(object obj) => obj is PTP_TIMER h ? handle == h.handle : false;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode() => handle.GetHashCode();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IntPtr DangerousGetHandle() => handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a handle to a threadpool wait.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct PTP_WAIT
|
public struct PTP_WAIT : IHandle
|
||||||
{
|
{
|
||||||
private readonly IntPtr handle;
|
private IntPtr handle;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="PTP_WAIT"/> struct.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
public PTP_WAIT(IntPtr preexistingHandle) => handle = preexistingHandle;
|
||||||
|
|
||||||
|
/// <summary>Returns an invalid handle by instantiating a <see cref="PTP_WAIT"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
||||||
|
public static PTP_WAIT NULL => new PTP_WAIT(IntPtr.Zero);
|
||||||
|
|
||||||
|
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
||||||
|
public bool IsNull => handle == IntPtr.Zero;
|
||||||
|
|
||||||
|
/// <summary>Performs an explicit conversion from <see cref="PTP_WAIT"/> to <see cref="IntPtr"/>.</summary>
|
||||||
|
/// <param name="h">The handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static explicit operator IntPtr(PTP_WAIT h) => h.handle;
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="PTP_WAIT"/>.</summary>
|
||||||
|
/// <param name="h">The pointer to a handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_WAIT(IntPtr h) => new PTP_WAIT(h);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator !=.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator !=(PTP_WAIT h1, PTP_WAIT h2) => !(h1 == h2);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator ==.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator ==(PTP_WAIT h1, PTP_WAIT h2) => h1.Equals(h2);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals(object obj) => obj is PTP_WAIT h ? handle == h.handle : false;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode() => handle.GetHashCode();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IntPtr DangerousGetHandle() => handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a handle to a threadpool work.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct PTP_WORK
|
public struct PTP_WORK : IHandle
|
||||||
{
|
{
|
||||||
private readonly IntPtr handle;
|
private IntPtr handle;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="PTP_WORK"/> struct.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
public PTP_WORK(IntPtr preexistingHandle) => handle = preexistingHandle;
|
||||||
|
|
||||||
|
/// <summary>Returns an invalid handle by instantiating a <see cref="PTP_WORK"/> object with <see cref="IntPtr.Zero"/>.</summary>
|
||||||
|
public static PTP_WORK NULL => new PTP_WORK(IntPtr.Zero);
|
||||||
|
|
||||||
|
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
|
||||||
|
public bool IsNull => handle == IntPtr.Zero;
|
||||||
|
|
||||||
|
/// <summary>Performs an explicit conversion from <see cref="PTP_WORK"/> to <see cref="IntPtr"/>.</summary>
|
||||||
|
/// <param name="h">The handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static explicit operator IntPtr(PTP_WORK h) => h.handle;
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="PTP_WORK"/>.</summary>
|
||||||
|
/// <param name="h">The pointer to a handle.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_WORK(IntPtr h) => new PTP_WORK(h);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator !=.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator !=(PTP_WORK h1, PTP_WORK h2) => !(h1 == h2);
|
||||||
|
|
||||||
|
/// <summary>Implements the operator ==.</summary>
|
||||||
|
/// <param name="h1">The first handle.</param>
|
||||||
|
/// <param name="h2">The second handle.</param>
|
||||||
|
/// <returns>The result of the operator.</returns>
|
||||||
|
public static bool operator ==(PTP_WORK h1, PTP_WORK h2) => h1.Equals(h2);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override bool Equals(object obj) => obj is PTP_WORK h ? handle == h.handle : false;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode() => handle.GetHashCode();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IntPtr DangerousGetHandle() => handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Used to set the stack reserve and commit sizes for new threads in a thread pool.</summary>
|
/// <summary>Used to set the stack reserve and commit sizes for new threads in a thread pool.</summary>
|
||||||
|
@ -882,7 +1285,8 @@ namespace Vanara.PInvoke
|
||||||
public SizeT StackCommit;
|
public SizeT StackCommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Defines a callback environment.</summary>`
|
/// <summary>Defines a callback environment.</summary>
|
||||||
|
/// `
|
||||||
[PInvokeData("threadpoolapiset.h")]
|
[PInvokeData("threadpoolapiset.h")]
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public class PTP_CALLBACK_ENVIRON
|
public class PTP_CALLBACK_ENVIRON
|
||||||
|
@ -890,10 +1294,10 @@ namespace Vanara.PInvoke
|
||||||
internal uint Version;
|
internal uint Version;
|
||||||
internal PTP_POOL Pool;
|
internal PTP_POOL Pool;
|
||||||
internal PTP_CLEANUP_GROUP CleanupGroup;
|
internal PTP_CLEANUP_GROUP CleanupGroup;
|
||||||
internal PTP_CLEANUP_GROUP_CANCEL_CALLBACK CleanupGroupCancelCallback;
|
internal CleanupGroupCancelCallback CleanupGroupCancelCallback;
|
||||||
internal HINSTANCE RaceDll;
|
internal HINSTANCE RaceDll;
|
||||||
internal HACTCTX _ActivationContext;
|
internal HACTCTX _ActivationContext;
|
||||||
internal PTP_SIMPLE_CALLBACK _FinalizationCallback;
|
internal SimpleCallback _FinalizationCallback;
|
||||||
internal TP_CALLBACK_ENV_FLAGS Flags;
|
internal TP_CALLBACK_ENV_FLAGS Flags;
|
||||||
internal TP_CALLBACK_PRIORITY CallbackPriority;
|
internal TP_CALLBACK_PRIORITY CallbackPriority;
|
||||||
internal uint Size;
|
internal uint Size;
|
||||||
|
@ -911,11 +1315,221 @@ namespace Vanara.PInvoke
|
||||||
|
|
||||||
/// <summary>Indicates a function to call when the callback environment is finalized.</summary>
|
/// <summary>Indicates a function to call when the callback environment is finalized.</summary>
|
||||||
/// <value>Pointer to a TP_SIMPLE_CALLBACK structure indicating a function to call when the callback environment is finalized.</value>
|
/// <value>Pointer to a TP_SIMPLE_CALLBACK structure indicating a function to call when the callback environment is finalized.</value>
|
||||||
public PTP_SIMPLE_CALLBACK FinalizationCallback { set => _FinalizationCallback = value; }
|
public SimpleCallback FinalizationCallback { set => _FinalizationCallback = value; }
|
||||||
|
|
||||||
/// <summary>Assigns an activation context to the callback environment.</summary>
|
/// <summary>Assigns an activation context to the callback environment.</summary>
|
||||||
/// <value>Pointer to an _ACTIVATION_CONTEXT structure.</value>
|
/// <value>Pointer to an _ACTIVATION_CONTEXT structure.</value>
|
||||||
public HACTCTX ActivationContext { set => _ActivationContext = value; }
|
public HACTCTX ActivationContext { set => _ActivationContext = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="PTP_CLEANUP_GROUP"/> that is disposed using <see cref="CloseThreadpoolCleanupGroup"/>.</summary>
|
||||||
|
public class SafePTP_CLEANUP_GROUP : SafeHANDLE
|
||||||
|
{
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_CLEANUP_GROUP"/> class and assigns an existing handle.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
/// <param name="ownsHandle">
|
||||||
|
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||||
|
/// </param>
|
||||||
|
public SafePTP_CLEANUP_GROUP(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_CLEANUP_GROUP"/> class.</summary>
|
||||||
|
private SafePTP_CLEANUP_GROUP() : base() { }
|
||||||
|
|
||||||
|
/// <summary>Gets or sets a value indicating whether to call CloseThreadpoolCleanupGroupMembers on disposal.</summary>
|
||||||
|
public bool AutoCloseMembers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="SafePTP_CLEANUP_GROUP"/> to <see cref="PTP_CLEANUP_GROUP"/>.</summary>
|
||||||
|
/// <param name="h">The safe handle instance.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_CLEANUP_GROUP(SafePTP_CLEANUP_GROUP h) => h.handle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the members of this cleanup group, waits for all callback functions to complete, and optionally cancels any
|
||||||
|
/// outstanding callback functions.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fCancelPendingCallbacks">
|
||||||
|
/// If this parameter is TRUE, the function cancels outstanding callbacks that have not yet started. If this parameter is FALSE,
|
||||||
|
/// the function waits for outstanding callback functions to complete.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="pvCleanupContext">
|
||||||
|
/// The application-defined data to pass to the application's cleanup group callback function. You can specify the callback
|
||||||
|
/// function when you call <c>SetThreadpoolCallbackCleanupGroup</c>.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>This function does not return a value.</returns>
|
||||||
|
public void CloseMembers(bool fCancelPendingCallbacks, [Optional] IntPtr pvCleanupContext) => CloseThreadpoolCleanupGroupMembers(handle, fCancelPendingCallbacks, pvCleanupContext);
|
||||||
|
|
||||||
|
/// <summary>Creates a new timer object.</summary>
|
||||||
|
/// <param name="pfnti">The callback function to call each time the timer object expires. For details, see <c>TimerCallback</c>.</param>
|
||||||
|
/// <param name="pv">Optional application-defined data to pass to the callback function.</param>
|
||||||
|
/// <param name="pcbe">
|
||||||
|
/// <para>
|
||||||
|
/// A <c>TP_CALLBACK_ENVIRON</c> structure that defines the environment in which to execute the callback. The
|
||||||
|
/// <c>InitializeThreadpoolEnvironment</c> function returns this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter is NULL, the callback executes in the default callback environment. For more information, see <c>InitializeThreadpoolEnvironment</c>.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// <para>
|
||||||
|
/// If the function succeeds, it returns a <c>TP_TIMER</c> structure that defines the timer object. Applications do not modify
|
||||||
|
/// the members of this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
|
/// </returns>
|
||||||
|
public PTP_TIMER CreateTimer(TimerCallback pfnti, IntPtr pv = default, PTP_CALLBACK_ENVIRON pcbe = null) => InternalCreateThreadpoolTimer(pfnti, pv, pcbe);
|
||||||
|
|
||||||
|
/// <summary>Creates a new wait object.</summary>
|
||||||
|
/// <param name="pfnwa">The callback function to call when the wait completes or times out. For details, see <c>WaitCallback</c>.</param>
|
||||||
|
/// <param name="pv">Optional application-defined data to pass to the callback function.</param>
|
||||||
|
/// <param name="pcbe">
|
||||||
|
/// <para>
|
||||||
|
/// A <c>TP_CALLBACK_ENVIRON</c> structure that defines the environment in which to execute the callback. The
|
||||||
|
/// <c>InitializeThreadpoolEnvironment</c> function returns this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter is NULL, the callback executes in the default callback environment. For more information, see <c>InitializeThreadpoolEnvironment</c>.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// <para>
|
||||||
|
/// If the function succeeds, it returns a <c>TP_WAIT</c> structure that defines the wait object. Applications do not modify the
|
||||||
|
/// members of this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
|
/// </returns>
|
||||||
|
public PTP_WAIT CreateWait(WaitCallback pfnwa, IntPtr pv = default, PTP_CALLBACK_ENVIRON pcbe = null) => InternalCreateThreadpoolWait(pfnwa, pv, pcbe);
|
||||||
|
|
||||||
|
/// <summary>Creates a new work object.</summary>
|
||||||
|
/// <param name="pfnwk">
|
||||||
|
/// The callback function. A worker thread calls this callback each time you call <c>SubmitThreadpoolWork</c> to post the work
|
||||||
|
/// object. For details, see <c>WorkCallback</c>.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="pv">Optional application-defined data to pass to the callback function.</param>
|
||||||
|
/// <param name="pcbe">
|
||||||
|
/// <para>
|
||||||
|
/// A <c>TP_CALLBACK_ENVIRON</c> structure that defines the environment in which to execute the callback. The
|
||||||
|
/// <c>InitializeThreadpoolEnvironment</c> function returns this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If this parameter is NULL, the callback executes in the default callback environment. For more information, see <c>InitializeThreadpoolEnvironment</c>.</para>
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// <para>
|
||||||
|
/// If the function succeeds, it returns a <c>TP_WORK</c> structure that defines the work object. Applications do not modify the
|
||||||
|
/// members of this structure.
|
||||||
|
/// </para>
|
||||||
|
/// <para>If the function fails, it returns NULL. To retrieve extended error information, call <c>GetLastError</c>.</para>
|
||||||
|
/// </returns>
|
||||||
|
public PTP_WORK CreateWork(WorkCallback pfnwk, IntPtr pv = default, PTP_CALLBACK_ENVIRON pcbe = null) => InternalCreateThreadpoolWork(pfnwk, pv, pcbe);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override bool InternalReleaseHandle() { if (AutoCloseMembers) CloseMembers(false); CloseThreadpoolCleanupGroup(handle); return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="PTP_IO"/> that is disposed using <see cref="CloseThreadpoolIo"/>.</summary>
|
||||||
|
public class SafePTP_IO : SafeHANDLE
|
||||||
|
{
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_IO"/> class and assigns an existing handle.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
/// <param name="ownsHandle">
|
||||||
|
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||||
|
/// </param>
|
||||||
|
public SafePTP_IO(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_IO"/> class.</summary>
|
||||||
|
private SafePTP_IO() : base() { }
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="SafePTP_IO"/> to <see cref="PTP_IO"/>.</summary>
|
||||||
|
/// <param name="h">The safe handle instance.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_IO(SafePTP_IO h) => h.handle;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override bool InternalReleaseHandle() { CloseThreadpoolIo(handle); return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="PTP_POOL"/> that is disposed using <see cref="CloseThreadpool"/>.</summary>
|
||||||
|
public class SafePTP_POOL : SafeHANDLE
|
||||||
|
{
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_POOL"/> class and assigns an existing handle.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
/// <param name="ownsHandle">
|
||||||
|
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||||
|
/// </param>
|
||||||
|
public SafePTP_POOL(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_POOL"/> class.</summary>
|
||||||
|
private SafePTP_POOL() : base() { }
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="SafePTP_POOL"/> to <see cref="PTP_POOL"/>.</summary>
|
||||||
|
/// <param name="h">The safe handle instance.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_POOL(SafePTP_POOL h) => h.handle;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override bool InternalReleaseHandle() { CloseThreadpool(handle); return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="PTP_TIMER"/> that is disposed using <see cref="CloseThreadpoolTimer"/>.</summary>
|
||||||
|
public class SafePTP_TIMER : SafeHANDLE
|
||||||
|
{
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_TIMER"/> class and assigns an existing handle.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
/// <param name="ownsHandle">
|
||||||
|
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||||
|
/// </param>
|
||||||
|
public SafePTP_TIMER(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_TIMER"/> class.</summary>
|
||||||
|
private SafePTP_TIMER() : base() { }
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="SafePTP_TIMER"/> to <see cref="PTP_TIMER"/>.</summary>
|
||||||
|
/// <param name="h">The safe handle instance.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_TIMER(SafePTP_TIMER h) => h.handle;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override bool InternalReleaseHandle() { CloseThreadpoolTimer(handle); return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="PTP_WAIT"/> that is disposed using <see cref="CloseThreadpoolWait"/>.</summary>
|
||||||
|
public class SafePTP_WAIT : SafeHANDLE
|
||||||
|
{
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_WAIT"/> class and assigns an existing handle.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
/// <param name="ownsHandle">
|
||||||
|
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||||
|
/// </param>
|
||||||
|
public SafePTP_WAIT(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_WAIT"/> class.</summary>
|
||||||
|
private SafePTP_WAIT() : base() { }
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="SafePTP_WAIT"/> to <see cref="PTP_WAIT"/>.</summary>
|
||||||
|
/// <param name="h">The safe handle instance.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_WAIT(SafePTP_WAIT h) => h.handle;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override bool InternalReleaseHandle() { CloseThreadpoolWait(handle); return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="PTP_WORK"/> that is disposed using <see cref="CloseThreadpoolWork"/>.</summary>
|
||||||
|
public class SafePTP_WORK : SafeHANDLE
|
||||||
|
{
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_WORK"/> class and assigns an existing handle.</summary>
|
||||||
|
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||||
|
/// <param name="ownsHandle">
|
||||||
|
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||||
|
/// </param>
|
||||||
|
public SafePTP_WORK(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="SafePTP_WORK"/> class.</summary>
|
||||||
|
private SafePTP_WORK() : base() { }
|
||||||
|
|
||||||
|
/// <summary>Performs an implicit conversion from <see cref="SafePTP_WORK"/> to <see cref="PTP_WORK"/>.</summary>
|
||||||
|
/// <param name="h">The safe handle instance.</param>
|
||||||
|
/// <returns>The result of the conversion.</returns>
|
||||||
|
public static implicit operator PTP_WORK(SafePTP_WORK h) => h.handle;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override bool InternalReleaseHandle() { CloseThreadpoolWork(handle); return true; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -48,6 +48,7 @@
|
||||||
<Compile Include="AppModelTests.cs" />
|
<Compile Include="AppModelTests.cs" />
|
||||||
<Compile Include="InterlockedApiTests.cs" />
|
<Compile Include="InterlockedApiTests.cs" />
|
||||||
<Compile Include="InteropServices\SafeLocalHandleTests.cs" />
|
<Compile Include="InteropServices\SafeLocalHandleTests.cs" />
|
||||||
|
<Compile Include="ThreadPoolApiSetTests.cs" />
|
||||||
<Compile Include="SystemTopologyTests.cs" />
|
<Compile Include="SystemTopologyTests.cs" />
|
||||||
<Compile Include="SynchApiTests.cs" />
|
<Compile Include="SynchApiTests.cs" />
|
||||||
<Compile Include="StringApiSetTests.cs" />
|
<Compile Include="StringApiSetTests.cs" />
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Vanara.Extensions;
|
||||||
|
using static Vanara.PInvoke.Kernel32;
|
||||||
|
|
||||||
|
namespace Vanara.PInvoke.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ThreadPoolApiSetTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void QuerySetThreadpoolStackInformationTest()
|
||||||
|
{
|
||||||
|
using (var pool = CreateThreadpool())
|
||||||
|
{
|
||||||
|
Assert.That(pool, ResultIs.ValidHandle);
|
||||||
|
Assert.That(QueryThreadpoolStackInformation(pool, out var si), ResultIs.Successful);
|
||||||
|
Assert.That(si.StackReserve.Value, Is.Not.Zero);
|
||||||
|
Assert.That(SetThreadpoolStackInformation(pool, si), ResultIs.Successful);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ThreadpoolIoWorkTimerTest()
|
||||||
|
{
|
||||||
|
InitializeThreadpoolEnvironment(out var CallBackEnviron);
|
||||||
|
|
||||||
|
// Create a custom, dedicated thread pool.
|
||||||
|
using (var pool = CreateThreadpool())
|
||||||
|
{
|
||||||
|
Assert.That(pool, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
// The thread pool is made persistent simply by setting both the minimum and maximum threads to 1.
|
||||||
|
SetThreadpoolThreadMaximum(pool, 1);
|
||||||
|
Assert.That(SetThreadpoolThreadMinimum(pool, 1), ResultIs.Successful);
|
||||||
|
|
||||||
|
// Create a cleanup group for this thread pool.
|
||||||
|
using (var cleanupgroup = CreateThreadpoolCleanupGroup())
|
||||||
|
{
|
||||||
|
Assert.That(cleanupgroup, ResultIs.ValidHandle);
|
||||||
|
cleanupgroup.AutoCloseMembers = true;
|
||||||
|
|
||||||
|
// Associate the callback environment with our thread pool.
|
||||||
|
CallBackEnviron.SetThreadpoolCallbackPool(pool);
|
||||||
|
|
||||||
|
// Associate the cleanup group with our thread pool. Objects created with the same callback environment as the cleanup
|
||||||
|
// group become members of the cleanup group.
|
||||||
|
CallBackEnviron.SetThreadpoolCallbackCleanupGroup(cleanupgroup, null);
|
||||||
|
|
||||||
|
// Create work with the callback environment.
|
||||||
|
var work = cleanupgroup.CreateWork(MyWorkCallback, default, CallBackEnviron);
|
||||||
|
Assert.That(work, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
// Submit the work to the pool. Because this was a pre-allocated work item (using CreateThreadpoolWork), it is guaranteed
|
||||||
|
// to execute.
|
||||||
|
SubmitThreadpoolWork(work);
|
||||||
|
|
||||||
|
// Create a timer with the same callback environment.
|
||||||
|
var timer = cleanupgroup.CreateTimer(MyTimerCallback, default, CallBackEnviron);
|
||||||
|
Assert.That(timer, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
// Set the timer to fire in one second.
|
||||||
|
var FileDueTime = TimeSpan.FromSeconds(-1).ToFileTimeStruct();
|
||||||
|
Assert.That(SetThreadpoolTimerEx(timer, FileDueTime, 0, 0), Is.False);
|
||||||
|
Assert.That(IsThreadpoolTimerSet(timer), Is.True);
|
||||||
|
|
||||||
|
using (var hFile = CreateFile(@"C:\Temp\help.ico", FileAccess.FILE_GENERIC_READ, System.IO.FileShare.Read, null, System.IO.FileMode.Open, FileFlagsAndAttributes.FILE_FLAG_OVERLAPPED))
|
||||||
|
using (var io = CreateThreadpoolIo(hFile, MyIoCallback, default, CallBackEnviron))
|
||||||
|
{
|
||||||
|
Assert.That(io, ResultIs.ValidHandle);
|
||||||
|
StartThreadpoolIo(io);
|
||||||
|
WaitForThreadpoolIoCallbacks(io, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay for the timer to be fired
|
||||||
|
Sleep(1500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyIoCallback(PTP_CALLBACK_INSTANCE Instance, IntPtr Context, IntPtr Overlapped, uint IoResult, UIntPtr NumberOfBytesTransferred, PTP_IO Io)
|
||||||
|
{
|
||||||
|
Debug.Write("MyIoCallback: I/O has fired.\n");
|
||||||
|
CancelThreadpoolIo(Io);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thread pool timer callback function template
|
||||||
|
void MyTimerCallback(PTP_CALLBACK_INSTANCE a, IntPtr b, PTP_TIMER c) => Debug.Write("MyTimerCallback: timer has fired.\n");
|
||||||
|
|
||||||
|
// This is the thread pool work callback function.
|
||||||
|
void MyWorkCallback(PTP_CALLBACK_INSTANCE a, IntPtr b, PTP_WORK c)
|
||||||
|
{
|
||||||
|
CallbackMayRunLong(a);
|
||||||
|
Debug.Write("MyWorkCallback: Task performed.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ThreadpoolWaitTest()
|
||||||
|
{
|
||||||
|
SafeEventHandle retEvent;
|
||||||
|
// Create an auto-reset event.
|
||||||
|
using (var hEvent = CreateEvent(null, false, false, null))
|
||||||
|
using (retEvent = CreateEvent(null, false, false, null))
|
||||||
|
{
|
||||||
|
Assert.That(hEvent, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
using (var Wait = CreateThreadpoolWait(MyWaitCallback))
|
||||||
|
{
|
||||||
|
Assert.That(Wait, ResultIs.ValidHandle);
|
||||||
|
|
||||||
|
// Need to re-register the event with the wait object each time before signaling the event to trigger the wait callback.
|
||||||
|
for (var i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
SetThreadpoolWait(Wait, hEvent);
|
||||||
|
|
||||||
|
SetEvent(hEvent);
|
||||||
|
|
||||||
|
// Delay for the waiter thread to act if necessary.
|
||||||
|
Sleep(500);
|
||||||
|
|
||||||
|
// Block here until the callback function is done executing.
|
||||||
|
WaitForThreadpoolWaitCallbacks(Wait, false);
|
||||||
|
|
||||||
|
// Ensure that callback return event is signaled.
|
||||||
|
WaitForSingleObject(retEvent, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetThreadpoolWait(Wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thread pool wait callback function template
|
||||||
|
void MyWaitCallback(PTP_CALLBACK_INSTANCE a, IntPtr b, PTP_WAIT c, uint d)
|
||||||
|
{
|
||||||
|
Debug.Write("MyWaitCallback: wait is over.\n");
|
||||||
|
Sleep(200);
|
||||||
|
SetEventWhenCallbackReturns(a, retEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TrySubmitThreadpoolCallbackTest()
|
||||||
|
{
|
||||||
|
Assert.That(TrySubmitThreadpoolCallback((i, c) =>
|
||||||
|
{
|
||||||
|
Debug.WriteLine("SimpleCallback from TrySubmitThreadpoolCallback");
|
||||||
|
DisassociateCurrentThreadFromCallback(i);
|
||||||
|
}), Is.True); ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue