gpt4 book ai didi

c# - 在 await 锁定期间 sleep 的正确方法

转载 作者:行者123 更新时间:2023-11-30 19:43:45 24 4
gpt4 key购买 nike

在我的 win8(winrt、c#)应用程序中,我需要调用一个 Web API,它有一个非常具体的限制:不再每 2 秒调用一次 Web 服务。

我试图强制执行此限制,如下所示:

class Client
{
const int Delay = 2000;
HttpClient m_client = new HttpClient();
int m_ticks = 0;

public async Task<string> Get(string url)
{
// Multiple threads could be calling, I need to protect access to m_ticks:
string result = null;
lock (this)
{
int ticks = Environment.TickCount - m_ticks;
if (ticks < Delay)
await Task.Delay(Delay - ticks);

result = await m_client.GetStringAsync(url);

m_ticks = Environment.TickCount;
}

return result;
}
}

这让我碰壁了:

  1. 我不能在锁中使用 await 语句。
  2. 我不能回退到像 WebClient + Thread.Sleep 这样的东西(避免异步废话),因为它在 win8 客户端配置文件中不存在。
  3. 我无法避免此方法是“异步”的,因为如果不在异步函数中,我就无法等待 GetStringAsync 或 Task.Delay。
  4. 我无法避免锁定,因为多个线程可能会调用此函数,而我需要同步访问 m_ticks。

我到底要怎么写这样的东西?

最佳答案

SemaphoreSlim类型在 .NET 4.5 中得到了扩展,以包括 await 兼容的 WaitAsync 方法。它没有基于 IDisposableRelease,但构建一个并不难:

sealed class SemaphoreSlimReleaser : IDisposable
{
SemaphoreSlim mutex;
public SemaphoreSlimReleaser(SemaphoreSlim mutex)
{
this.mutex = mutex;
}

void Dispose()
{
if (mutex == null)
return;
mutex.Release();
mutex = null;
}
}

然后您可以使用与您已有的代码非常相似的代码:

class Client
{
const int Delay = 2000;
HttpClient m_client = new HttpClient();
int m_ticks = 0;
SemaphoreSlim mutex = new SemaphoreSlim(1);

public async Task<string> Get(string url)
{
// Multiple threads could be calling, I need to protect access to m_ticks:
string result = null;
await mutex.WaitAsync();
using (new SemaphoreSlimReleaser(mutex))
{
int ticks = Environment.TickCount - m_ticks;
if (ticks < Delay)
await Task.Delay(Delay - ticks);

result = await m_client.GetStringAsync(url);

m_ticks = Environment.TickCount;
}

return result;
}
}

附言如果您有兴趣,我的 AsyncEx 库有一个 full suite of async-compatible synchronization primitives灵感来自 Stephen Toub's blog series .

关于c# - 在 await 锁定期间 sleep 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14180915/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com