在 C# 中的异步方法中,我需要推迟执行(将执行返回给调用者),并在继续执行之前清除同步上下文。
语句“await Task.Delay(1).ConfigureAwait(false);”在方法开始时会这样做,但由于延迟,平均性能损失为 15 毫秒。
推迟和清除执行上下文的更好方法是检查当前执行上下文并调用 Task.Yield (它保留执行上下文,如果有)或 Task.Delay(1).ConfigureAwait(false):
public async Task Test()
{
if (SynchronizationContext.Current is null)
{
await Task.Yield();
}
else
{
await Task.Delay(1).ConfigureAwait(false);
}
// Deferred code
}
你知道是否有更简单的方法来推迟当前任务的执行(如Task.Yield)并同时清除同步上下文?
我不能这样做,因为 Task.Yield 和 Task.ConfigureAwait 对可等待/等待值使用不同的结构:
public async ??? TaskYieldNoSyncContext() =>
(SynchronizationContext.Current is null)
? Task.Yield()
: Task.Delay(1).ConfigureAwait(false);
public async Task Test()
{
await TaskYieldNoSyncContext();
// Deferred code
}
因此,我创建以下内容将ConfiguredTaskAwaitable/ConfiguredTaskAwaiter 和 YieldAwaitable/YieldAwaiter 合并到单个嵌套结构中:
具有“await”关键字所需实现的接口:
public interface ICustomAwaitable
{
public ICustomAwaiter GetAwaiter();
public interface ICustomAwaiter : ICriticalNotifyCompletion
{
public bool IsCompleted { get; }
public void GetResult();
}
}
ConfiguredTaskAwaitable/ConfiguredTaskAwaiter 的实现:
public struct CustomAwaitableTask : ICustomAwaitable
{
private readonly ConfiguredTaskAwaitable _awaitable;
public CustomAwaitableTask(ConfiguredTaskAwaitable awaitable)
{
_awaitable = awaitable;
}
public ICustomAwaitable.ICustomAwaiter GetAwaiter() { return new CustomAwaiterTask(_awaitable.GetAwaiter()); }
public struct CustomAwaiterTask : ICustomAwaitable.ICustomAwaiter
{
private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter _awaiter;
public CustomAwaiterTask(ConfiguredTaskAwaitable.ConfiguredTaskAwaiter awaiter)
{
_awaiter = awaiter;
}
public bool IsCompleted => _awaiter.IsCompleted;
public void OnCompleted(Action continuation) => _awaiter.OnCompleted(continuation: continuation);
public void UnsafeOnCompleted(Action continuation) => _awaiter.UnsafeOnCompleted(continuation: continuation);
public void GetResult() => _awaiter.GetResult();
}
}
YieldAwaitable/YieldAwaiter 的实现:
public struct CustomAwaitableYield : ICustomAwaitable
{
private readonly YieldAwaitable _awaitable;
public CustomAwaitableYield(YieldAwaitable awaitable)
{
_awaitable = awaitable;
}
public ICustomAwaitable.ICustomAwaiter GetAwaiter() { return new CustomAwaiterYield(_awaitable.GetAwaiter()); }
public struct CustomAwaiterYield : ICustomAwaitable.ICustomAwaiter
{
private readonly YieldAwaitable.YieldAwaiter _awaiter;
public CustomAwaiterYield(YieldAwaitable.YieldAwaiter awaiter)
{
_awaiter = awaiter;
}
public bool IsCompleted => _awaiter.IsCompleted;
public void OnCompleted(Action continuation) => _awaiter.OnCompleted(continuation: continuation);
public void UnsafeOnCompleted(Action continuation) => _awaiter.UnsafeOnCompleted(continuation: continuation);
public void GetResult() => _awaiter.GetResult();
}
}
以及根据当前同步上下文返回这些实现之一的静态方法:
public static ICustomAwaitable YieldNoSyncContext()
{
if (SynchronizationContext.Current is null)
{
return new CustomAwaitableYield(Task.Yield());
}
else
{
return new CustomAwaitableTask(Task.Delay(1).ConfigureAwait(false));
}
}
这样我就可以推迟任务并以最小的性能影响清除同步:
public async Task Test()
{
await TaskYieldNoSyncContext();
// Deferred code
}