【问题标题】:How can I prevent an async method from being reentrant?如何防止异步方法可重入?
【发布时间】:2020-05-08 20:12:12
【问题描述】:

我的程序中有一个异步方法。我需要任务是异步的,因为它会发出网络请求,但我不希望它是可重入的。换句话说,如果在第一次调用返回之前从代码块 A 调用该方法,然后再从代码块 B 调用该方法,我希望第二次调用等到第一次调用完成后再运行。

如果该方法不是异步方法,我可以使用以下注释来完成它: [MethodImpl(MethodImplOptions.Synchronized)]

但是,编译器不允许将注解附加到异步方法。

我还能做什么?

【问题讨论】:

  • 你可以G。使用SemaphoreSlim 之类的东西一次只让一个线程进入方法。
  • Synchronized 只是一个隐含的lock,虽然你不能在async 方法中使用lock,但确实存在SemaphoreSlimAsyncLock 之类的东西来实现相互以异步方式排除。顺便说一句,即使在同步代码中也不要使用Synchronized——它基本上就在那里,因为 Java 有它,但它所隐含的lock (this) 比锁定为此目的明确声明的私有字段要糟糕得多。

标签: c# .net uwp async-await


【解决方案1】:

您可以使用SemaphoreSlim,它是一个带有WaitAsync 方法的锁(它不介意您将它释放到与您获取它的线程不同的线程上)。

private readonly SemaphoreSlim methodLock = new SemaphoreSlim(1, 1);

public async Task SomeMethod()
{
    await methodLock.WaitAsync();
    try
    {
        ...
    }
    finally
    {
        methodLock.Release();
    }
}

如果你喜欢冒险,你可以在 SemaphoreSlim 上写一个扩展方法,让你做例如:

public async Task SomeMethod()
{
    using (await methodLock.WaitDisposableAsync())
    {
        ...
    }
}

但要小心:SemaphoreSlim 不是递归的(也不可能)。这意味着如果你的方法是递归的,它就会死锁。

【讨论】:

  • 酷,感谢您的回复。我会试一试,听起来像我需要的。
猜你喜欢
  • 1970-01-01
  • 2021-03-25
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多