简体   繁体   中英

What's the equivalent to Unwrap for a ConfiguredTaskAwaitable?

I'm creating a (well adapting an existing) helper class to allow me to run async methods synchronously. So far I've got the task factory and a static method that lets me run async methods synchronously as long as I don't configure them with .ConfigureAwait , because .ConfigureAwait turns the return value of the method from a System.Threading.Tasks.Task<T> to a System.Runtime.CompilerServices.ConfiguredTaskAwaitable<T> . The code looks like this:

public static class AsyncUtils {
    private static readonly TaskFactory _taskFactory =
        new TaskFactory(
            CancellationToken.None,
            TaskCreationOptions.None,
            TaskContinuationOptions.None,
            TaskScheduler.Default
        );

    public static TResult RunSync<TResult>(Func<Task<TResult>> func) {
        return _taskFactory
            .StartNew<Task<TResult>>(func)
            .Unwrap<TResult>()
            .GetAwaiter()
            .GetResult();
    }
}

If I try to add a method to deal with ConfiguredTaskAwaitable<T> , it might look like this:

    public static TResult RunSync<TResult>(Func<ConfiguredTaskAwaitable<TResult>> func) {
        return _taskFactory
            .StartNew<ConfiguredTaskAwaitable<TResult>>(func)
            .Unwrap<TResult>() // Doesn't exist!
            .GetAwaiter()
            .GetResult();
    }

The trouble is, as can be seen from the comment, StartNew<ConfiguredTaskAwaitable> returns a Task<ConfiguredTaskAwaitable<TResult>> instead of a Task<Task<TResult>> meaning that the Unwrap method doesn't exist for it. Is there an equivalent? How can I create an equivalent method for ConfiguredTaskAwaitable ?

ConfigureAwait() only controls how the context is resumed after an await . If you're getting the result synchronously, it will have no effect because there is no "resume".

Additionally, one would typically run async methods synchronously by just doing this:

TResult RunSync<TResult>(Func<Task<TResult>> func) {
    return func().Result;
}

Or this, if you want to force it to run on the thread pool:

TResult RunSync<TResult>(Func<Task<TResult>> func) {
    return Task.Run(func).Result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM