如何通过 TaskCompletionSource 将任务状态设置为 "Running"
How can I set the state of a task to "Running" via TaskCompletionSource
在我的程序中的某些情况下,我使用 TaskCompletionSource
创建任务并操纵其状态。
在其他情况下,任务以“常规”方式创建和执行。
在常规任务创建和执行的情况下,任务在执行时的状态为“运行”。这个“运行”状态在其他地方被检查以确保任务正在执行?
如何在使用 TaskCompletionSource
时在任务上设置此状态?如果我不将状态设置为“运行”,则上述检查将失败。
我发现实现这一目标的唯一方法是通过反射。以下解决方案已经过测试并且有效。
private const string s_fieldName_StateFlags = "m_stateFlags";
/// <summary> From https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs </summary>
[Flags]
public enum TaskState
{
TASK_STATE_STARTED = 0x10000, //bin: 0000 0000 0000 0001 0000 0000 0000 0000
TASK_STATE_DELEGATE_INVOKED = 0x20000, //bin: 0000 0000 0000 0010 0000 0000 0000 0000
TASK_STATE_DISPOSED = 0x40000, //bin: 0000 0000 0000 0100 0000 0000 0000 0000
TASK_STATE_EXCEPTIONOBSERVEDBYPARENT = 0x80000, //bin: 0000 0000 0000 1000 0000 0000 0000 0000
TASK_STATE_CANCELLATIONACKNOWLEDGED = 0x100000, //bin: 0000 0000 0001 0000 0000 0000 0000 0000
TASK_STATE_FAULTED = 0x200000, //bin: 0000 0000 0010 0000 0000 0000 0000 0000
TASK_STATE_CANCELED = 0x400000, //bin: 0000 0000 0100 0000 0000 0000 0000 0000
TASK_STATE_WAITING_ON_CHILDREN = 0x800000, //bin: 0000 0000 1000 0000 0000 0000 0000 0000
TASK_STATE_RAN_TO_COMPLETION = 0x1000000, //bin: 0000 0001 0000 0000 0000 0000 0000 0000
TASK_STATE_WAITINGFORACTIVATION = 0x2000000, //bin: 0000 0010 0000 0000 0000 0000 0000 0000
TASK_STATE_COMPLETION_RESERVED = 0x4000000, //bin: 0000 0100 0000 0000 0000 0000 0000 0000
TASK_STATE_THREAD_WAS_ABORTED = 0x8000000, //bin: 0000 1000 0000 0000 0000 0000 0000 0000
TASK_STATE_WAIT_COMPLETION_NOTIFICATION = 0x10000000, //bin: 0001 0000 0000 0000 0000 0000 0000 0000
TASK_STATE_EXECUTIONCONTEXT_IS_NULL = 0x20000000, //bin: 0010 0000 0000 0000 0000 0000 0000 0000
TASK_STATE_TASKSCHEDULED_WAS_FIRED = 0x40000000, //bin: 0100 0000 0000 0000 0000 0000 0000 0000
}
public static void SetTaskRunning<TResult> (TaskCompletionSource<TResult> i_taskCompletionSource)
{
if (i_taskCompletionSource == null)
throw new ArgumentNullException (nameof (i_taskCompletionSource));
var value = TaskState.TASK_STATE_STARTED
| TaskState.TASK_STATE_DELEGATE_INVOKED;
var task = i_taskCompletionSource.Task;
var type = task.GetType ();
var fieldInfo = type.GetField (s_fieldName_StateFlags, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
fieldInfo.SetValue (task, (int)value);
}
在我的程序中的某些情况下,我使用 TaskCompletionSource
创建任务并操纵其状态。
在其他情况下,任务以“常规”方式创建和执行。
在常规任务创建和执行的情况下,任务在执行时的状态为“运行”。这个“运行”状态在其他地方被检查以确保任务正在执行?
如何在使用 TaskCompletionSource
时在任务上设置此状态?如果我不将状态设置为“运行”,则上述检查将失败。
我发现实现这一目标的唯一方法是通过反射。以下解决方案已经过测试并且有效。
private const string s_fieldName_StateFlags = "m_stateFlags";
/// <summary> From https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs </summary>
[Flags]
public enum TaskState
{
TASK_STATE_STARTED = 0x10000, //bin: 0000 0000 0000 0001 0000 0000 0000 0000
TASK_STATE_DELEGATE_INVOKED = 0x20000, //bin: 0000 0000 0000 0010 0000 0000 0000 0000
TASK_STATE_DISPOSED = 0x40000, //bin: 0000 0000 0000 0100 0000 0000 0000 0000
TASK_STATE_EXCEPTIONOBSERVEDBYPARENT = 0x80000, //bin: 0000 0000 0000 1000 0000 0000 0000 0000
TASK_STATE_CANCELLATIONACKNOWLEDGED = 0x100000, //bin: 0000 0000 0001 0000 0000 0000 0000 0000
TASK_STATE_FAULTED = 0x200000, //bin: 0000 0000 0010 0000 0000 0000 0000 0000
TASK_STATE_CANCELED = 0x400000, //bin: 0000 0000 0100 0000 0000 0000 0000 0000
TASK_STATE_WAITING_ON_CHILDREN = 0x800000, //bin: 0000 0000 1000 0000 0000 0000 0000 0000
TASK_STATE_RAN_TO_COMPLETION = 0x1000000, //bin: 0000 0001 0000 0000 0000 0000 0000 0000
TASK_STATE_WAITINGFORACTIVATION = 0x2000000, //bin: 0000 0010 0000 0000 0000 0000 0000 0000
TASK_STATE_COMPLETION_RESERVED = 0x4000000, //bin: 0000 0100 0000 0000 0000 0000 0000 0000
TASK_STATE_THREAD_WAS_ABORTED = 0x8000000, //bin: 0000 1000 0000 0000 0000 0000 0000 0000
TASK_STATE_WAIT_COMPLETION_NOTIFICATION = 0x10000000, //bin: 0001 0000 0000 0000 0000 0000 0000 0000
TASK_STATE_EXECUTIONCONTEXT_IS_NULL = 0x20000000, //bin: 0010 0000 0000 0000 0000 0000 0000 0000
TASK_STATE_TASKSCHEDULED_WAS_FIRED = 0x40000000, //bin: 0100 0000 0000 0000 0000 0000 0000 0000
}
public static void SetTaskRunning<TResult> (TaskCompletionSource<TResult> i_taskCompletionSource)
{
if (i_taskCompletionSource == null)
throw new ArgumentNullException (nameof (i_taskCompletionSource));
var value = TaskState.TASK_STATE_STARTED
| TaskState.TASK_STATE_DELEGATE_INVOKED;
var task = i_taskCompletionSource.Task;
var type = task.GetType ();
var fieldInfo = type.GetField (s_fieldName_StateFlags, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
fieldInfo.SetValue (task, (int)value);
}