当前位置:  开发笔记 > 编程语言 > 正文

一个聪明的技巧,防止在没有等待的C#using子句中使用Task <IDisposable>

如何解决《一个聪明的技巧,防止在没有等待的C#using子句中使用Task<IDisposable>》经验,为你挑选了1个好方法。

我有许多方法,目前返回等待Task.

有没有办法更改返回类型,以便以下将成为编译时错误?

using (GetExclusiveLockAsync())
{
    ...
}

我的想法是让编译器提醒我,我应该像这样编写它:

using (await GetExclusiveLockAsync())
{
    ...
}

实际上,GetExclusiveLockAsync返回Task也实现了IDisposable(通过基本Task类).两个片段都编译,但其中一个是错误的.我不想处理任务,只有它的结果!

是否有一个聪明的技巧使第一个编译时错误?

更新:根据目前的评论,似乎所展示的模式令人困惑.我现在已经将方法的名称从原始GetAsync更改GetExclusiveLockAsync为更好地说明实际的预期用途.它基本上是一个异步同步锁,这是我不需要using在行中声明变量也不需要在后面的块中使用它的主要原因.它仅用于保护它所包围的代码块免受并行影响.



1> Stephen Clea..:

是否有一个聪明的技巧使第一个编译时错误?

是的,您可以将返回类型更改为其他类型.

我在我的AsyncEx库中使用这种方法,使用AwaitableDisposable类型.简而言之:

public struct AwaitableDisposable where 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);
Task lockTask = GetExclusiveLockAsync();
using (await GetExclusiveLockAsync()) { }

在某些情况下,隐式转换是不够的,例如,某些Task.WhenAll用途.对于这些情况,用户可以致电AsTask:

// Not pretty, but doable.
await Task.WhenAll(x.GetExclusiveLockAsync().AsTask(),
    y.GetExclusiveLockAsync().AsTask());

当然,完整的目的AwaitableDisposable是它不是一次性的,所以这在编译时失败了:

using (GetExclusiveLockAsync()) { }

推荐阅读
wurtjq
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有