How can I prevent synchronous continuations on a Task?

后端 未结 6 482
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-27 11:04

I have some library (socket networking) code that provides a Task-based API for pending responses to requests, based on TaskCompletionSource

6条回答
  •  孤街浪徒
    2020-11-27 11:34

    New in .NET 4.6:

    .NET 4.6 contains a new TaskCreationOptions: RunContinuationsAsynchronously.


    Since you're willing to use Reflection to access private fields...

    You can mark the TCS's Task with the TASK_STATE_THREAD_WAS_ABORTED flag, which would cause all continuations not to be inlined.

    const int TASK_STATE_THREAD_WAS_ABORTED = 134217728;
    
    var stateField = typeof(Task).GetField("m_stateFlags", BindingFlags.NonPublic | BindingFlags.Instance);
    stateField.SetValue(task, (int) stateField.GetValue(task) | TASK_STATE_THREAD_WAS_ABORTED);
    

    Edit:

    Instead of using Reflection emit, I suggest you use expressions. This is much more readable and has the advantage of being PCL-compatible:

    var taskParameter = Expression.Parameter(typeof (Task));
    const string stateFlagsFieldName = "m_stateFlags";
    var setter =
        Expression.Lambda>(
            Expression.Assign(Expression.Field(taskParameter, stateFlagsFieldName),
                Expression.Or(Expression.Field(taskParameter, stateFlagsFieldName),
                    Expression.Constant(TASK_STATE_THREAD_WAS_ABORTED))), taskParameter).Compile();
    

    Without using Reflection:

    If anyone's interested, I've figured out a way to do this without Reflection, but it is a bit "dirty" as well, and of course carries a non-negligible perf penalty:

    try
    {
        Thread.CurrentThread.Abort();
    }
    catch (ThreadAbortException)
    {
        source.TrySetResult(123);
        Thread.ResetAbort();
    }
    

提交回复
热议问题