当 CPU 不受 "SemaphoreSlim.WaitAsync" 用法的影响时,有哪些替代方案?
When CPU is not affected of "SemaphoreSlim.WaitAsync" usage and what are alternatives?
我有一个执行长 运行 任务的程序,它应该在程序启动时启动,并且应该可以在之后的任何时刻重新启动。
我的目的是如果 "restart" 被调用,这会发生:
- 请求完成所有任务
- 等待所有任务完成
- 所有功能重新启动
我想使用 async/await 并仍然锁定启动所有任务的过程,以确保在之前的 start/restart 完成之前不会进行任何重启。
正如我看到的,出于多种原因 async/await 不适用于锁定状态,所以我最终使用了对我来说非常有用的 SemaphoreSlim。这是我的代码:
private readonly SemaphoreSlim m_semaphoreSlim;
private CancellationTokenSource m_cancellationTokenSource;
private CancellationToken m_cancellationToken;
public FeedClientService(IList<IFeedConfigurationBuilder> feedConfigs)
{
m_semaphoreSlim = new SemaphoreSlim(1, 1);
m_feedConfigs = feedConfigs;
}
public void Start()
{
Task.Run(() => this.FetchFeeds());
}
public void Restart()
{
if (m_cancellationTokenSource != null) m_cancellationTokenSource.Cancel();
Task.Run(() => this.FetchFeeds());
}
private async Task FetchFeeds()
{
try
{
await m_semaphoreSlim.WaitAsync();
m_cancellationTokenSource = new CancellationTokenSource();
m_cancellationToken = m_cancellationTokenSource.Token;
Task[] tasks = new Task[m_feedConfigs.Count];
for (int i = 0; i < m_feedConfigs.Count; i++)
{
var index = i;
tasks[index] = Task.Run(async () => await this.FetchFeed(index), m_cancellationToken);
}
await Task.WhenAll(tasks);
}
finally
{
m_semaphoreSlim.Release();
}
}
正如这里指出的那样 - "The SemaphoreSlim class represents a lightweight, fast semaphore that can be used for waiting within a single process when wait times are expected to be very short"。我还没有找到任何指定 "very short" 的来源,我不确定我的代码是否会有性能瓶颈,因为我开始的任务肯定不短 运行 。
TL;DR;
- "very short waiting times"是什么意思?
- 如果等待时间很长,有什么选择?
原来 SemaphoreSlim.WaitAsync
根本没有使用自旋等待技术(供参考 - implementation of SemaphoreSlim)。所以锁定资源,即使其中有很长的 运行 任务,也不会影响 CPU 消耗。
我有一个执行长 运行 任务的程序,它应该在程序启动时启动,并且应该可以在之后的任何时刻重新启动。
我的目的是如果 "restart" 被调用,这会发生:
- 请求完成所有任务
- 等待所有任务完成
- 所有功能重新启动
我想使用 async/await 并仍然锁定启动所有任务的过程,以确保在之前的 start/restart 完成之前不会进行任何重启。
正如我看到的,出于多种原因 async/await 不适用于锁定状态,所以我最终使用了对我来说非常有用的 SemaphoreSlim。这是我的代码:
private readonly SemaphoreSlim m_semaphoreSlim;
private CancellationTokenSource m_cancellationTokenSource;
private CancellationToken m_cancellationToken;
public FeedClientService(IList<IFeedConfigurationBuilder> feedConfigs)
{
m_semaphoreSlim = new SemaphoreSlim(1, 1);
m_feedConfigs = feedConfigs;
}
public void Start()
{
Task.Run(() => this.FetchFeeds());
}
public void Restart()
{
if (m_cancellationTokenSource != null) m_cancellationTokenSource.Cancel();
Task.Run(() => this.FetchFeeds());
}
private async Task FetchFeeds()
{
try
{
await m_semaphoreSlim.WaitAsync();
m_cancellationTokenSource = new CancellationTokenSource();
m_cancellationToken = m_cancellationTokenSource.Token;
Task[] tasks = new Task[m_feedConfigs.Count];
for (int i = 0; i < m_feedConfigs.Count; i++)
{
var index = i;
tasks[index] = Task.Run(async () => await this.FetchFeed(index), m_cancellationToken);
}
await Task.WhenAll(tasks);
}
finally
{
m_semaphoreSlim.Release();
}
}
正如这里指出的那样 - "The SemaphoreSlim class represents a lightweight, fast semaphore that can be used for waiting within a single process when wait times are expected to be very short"。我还没有找到任何指定 "very short" 的来源,我不确定我的代码是否会有性能瓶颈,因为我开始的任务肯定不短 运行 。
TL;DR;
- "very short waiting times"是什么意思?
- 如果等待时间很长,有什么选择?
原来 SemaphoreSlim.WaitAsync
根本没有使用自旋等待技术(供参考 - implementation of SemaphoreSlim)。所以锁定资源,即使其中有很长的 运行 任务,也不会影响 CPU 消耗。