我有许多方法,目前返回等待Task
.
有没有办法更改返回类型,以便以下将成为编译时错误?
using (GetExclusiveLockAsync()) { ... }
我的想法是让编译器提醒我,我应该像这样编写它:
using (await GetExclusiveLockAsync()) { ... }
实际上,GetExclusiveLockAsync返回Task
也实现了IDisposable(通过基本Task类).两个片段都编译,但其中一个是错误的.我不想处理任务,只有它的结果!
是否有一个聪明的技巧使第一个编译时错误?
更新:根据目前的评论,似乎所展示的模式令人困惑.我现在已经将方法的名称从原始GetAsync
更改GetExclusiveLockAsync
为更好地说明实际的预期用途.它基本上是一个异步同步锁,这是我不需要using
在行中声明变量也不需要在后面的块中使用它的主要原因.它仅用于保护它所包围的代码块免受并行影响.
是否有一个聪明的技巧使第一个编译时错误?
是的,您可以将返回类型更改为其他类型.
我在我的AsyncEx
库中使用这种方法,使用AwaitableDisposable
类型.简而言之:
public struct AwaitableDisposablewhere T : IDisposable { private readonly Task _task; public AwaitableDisposable(Task task) { _task = task; } public TaskAwaiter GetAwaiter() => _task.GetAwaiter(); public ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) => _task.ConfigureAwait(continueOnCapturedContext); public Task AsTask() => _task; public static implicit operator Task (AwaitableDisposable source) => source.AsTask(); }
你可以AwaitableDisposable
从你GetExclusiveLockAsync
而不是常规回来Task
.这是一个struct
最小的开销.
隐式转换和GetAwaiter
/ ConfigureAwait
方法允许"任务"使用:
// All of these work. IDisposable key = await GetExclusiveLockAsync(); IDisposable key = await GetExclusiveLockAsync().ConfigureAwait(false); TasklockTask = GetExclusiveLockAsync(); using (await GetExclusiveLockAsync()) { }
在某些情况下,隐式转换是不够的,例如,某些Task.WhenAll
用途.对于这些情况,用户可以致电AsTask
:
// Not pretty, but doable. await Task.WhenAll(x.GetExclusiveLockAsync().AsTask(), y.GetExclusiveLockAsync().AsTask());
当然,完整的目的AwaitableDisposable
是它不是一次性的,所以这在编译时失败了:
using (GetExclusiveLockAsync()) { }