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