gpt4 book ai didi

c# - 创建特定数量的任务\线程后如何等待特定时间?

转载 作者:行者123 更新时间:2023-11-30 16:06:08 25 4
gpt4 key购买 nike

我有一个要求,我可以在一秒钟内访问 API 5 次。如果我必须发出总共 50 个请求,我想发出前 5 个请求并等待 1 秒,然后我可以用另一批 5 个请求访问 API。我尝试使用线程池以及并行任务库 For\Foreach 循环和任务类,但我无法获得一个顺序计数器来告诉我已经创建了 5 个任务。这是我正在尝试做的示例:

List<string> str = new List<string>();
for (int i = 0; i <= 100; i++)
{
str.Add(i.ToString());
}

Parallel.ForEach(str, new ParallelOptions { MaxDegreeOfParallelism = 5 },
(value, pls, index) =>
{
Console.WriteLine(value);// simulating method call
if (index + 1 == 5)
{
// need the main thread to sleep so next batch is
Thread.Sleep(1000);
}
});

最佳答案

由于您使用的是 .NET 4.0(并且希望您至少使用 VS2012),您可以使用 Microsoft.Bcl.Async获得 async-await 特性。

一旦你这样做,你就可以轻松地异步查询你的 API 端点(不需要额外的线程),并使用 AsyncSemaphore(见下面的实现)来限制你做的请求数量同时。

例如:

public readonly AsyncSemaphore = new AsyncSemaphore(5);
public readonly HttpClient httpClient = new HttpClient();
public async Task<string> LimitedQueryAsync(string url)
{
await semaphoreSlim.WaitAsync();
try
{
var response = await httpClient.GetAsync(url);
return response.Content.ReadAsStringAsync();
}
finally
{
semaphoreSlim.Release();
}
}

现在你可以这样查询了:

public async Task DoQueryStuffAsync()
{
while (someCondition)
{
var results = await LimitedQueryAsync(url);

// do stuff with results
await Task.Delay(1000);
}
}

编辑:正如@ScottChamberlain 正确指出的那样,SemaphoreSlim 在 .NET 4 中不可用。您可以改为使用 AsyncSemaphore,如下所示:

public class AsyncSemaphore 
{
private readonly static Task s_completed = Task.FromResult(true);
private readonly Queue<TaskCompletionSource<bool>> m_waiters =
new Queue<TaskCompletionSource<bool>>();
private int m_currentCount;

public AsyncSemaphore(int initialCount)
{
if (initialCount < 0)
{
throw new ArgumentOutOfRangeException("initialCount");
}
m_currentCount = initialCount;
}

public Task WaitAsync()
{
lock (m_waiters)
{
if (m_currentCount > 0)
{
--m_currentCount;
return s_completed;
}
else
{
var waiter = new TaskCompletionSource<bool>();
m_waiters.Enqueue(waiter);
return waiter.Task;
}
}
}

public void Release()
{
TaskCompletionSource<bool> toRelease = null;
lock (m_waiters)
{
if (m_waiters.Count > 0)
toRelease = m_waiters.Dequeue();
else
++m_currentCount;
}
if (toRelease != null)
toRelease.SetResult(true);
}
}

关于c# - 创建特定数量的任务\线程后如何等待特定时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32695074/

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