如何使用任务.延迟用于控制对web服务的调用之间的时间跨度
本文关键字:服务 调用 之间 时间跨度 web 任务 何使用 延迟 用于 控制 | 更新日期: 2023-09-27 18:18:34
当用户执行某个操作时,将对web服务进行调用(get)。该服务不允许通话频率超过每秒一次。我想我可以用任务组。延迟控制这一点,以便后续呼叫至少间隔一秒钟,但它似乎不像预期的那样工作。伪代码看起来像这样:
public async void OnUserAction()
{
var timeUntilPreviousCallWillBeOrWasMade = 1000ms - (Now - previousWaitStartTime);
var timeToWaitBeforeThisCallShouldBeMade = Max(0, timeUntilPreviousCallWillBeOrWasMade + 1000ms);
previousWaitStartTime = Now;
await Task.Delay(timeToWaitBeforeThisCallShouldBeMade);
MakeCallToWebService();
}
调用和延续在同一个线程上完成(由Environment.CurrentManagedThreadId报告)。问题是,如果这个方法有一个快速的连续调用,那么调用web服务之间的间隔时间小于15秒。要么我犯了一个愚蠢的错误,要么我没有完全理解Task。延迟(或两者都延迟)。有提示吗?
当另一个请求已经在等待时,您的问题似乎发生在请求排队时。以下是我对你的伪代码的看法:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ThrottledAsync
{
class Program
{
static void Main(string[] args)
{
// Queue up multiple user actions
// within a short interval.
for (var i = 0; i < 10; i++)
{
OnUserAction();
Thread.Sleep(10);
}
Console.ReadLine();
}
private static int UserActionID;
private static DateTime previousWaitStartTime;
public static async void OnUserAction()
{
// Keep track of the operation ID.
var userActionID = Interlocked.Increment(ref UserActionID);
// Pseudo-code implementation.
var timeUntilPreviousCallWillBeOrWasMade = 1000 - (int)(DateTime.Now.Subtract(previousWaitStartTime).TotalMilliseconds);
Console.WriteLine(
"{0:HH:mm:ss.ffff} - User action {1}: timeUntilPreviousCallWillBeOrWasMade = {2}.",
DateTime.Now, userActionID, timeUntilPreviousCallWillBeOrWasMade);
var timeToWaitBeforeThisCallShouldBeMade = Math.Max(0, timeUntilPreviousCallWillBeOrWasMade + 1000);
Console.WriteLine(
"{0:HH:mm:ss.ffff} - User action {1}: timeToWaitBeforeThisCallShouldBeMade = {2}.",
DateTime.Now, userActionID, timeToWaitBeforeThisCallShouldBeMade);
previousWaitStartTime = DateTime.Now;
await Task.Delay(timeToWaitBeforeThisCallShouldBeMade);
await MakeCallToWebService(userActionID);
}
private static async Task MakeCallToWebService(int userActionID)
{
// Simulate network delay.
await Task.Delay(new Random().Next(5, 10));
Console.WriteLine("{0:HH:mm:ss.ffff} - User action {1}: web service call.", DateTime.Now, userActionID);
}
}
}
输出:
19:10:11.1366 - User action 1: timeUntilPreviousCallWillBeOrWasMade = -2147482648.
19:10:11.1416 - User action 1: timeToWaitBeforeThisCallShouldBeMade = 0.
19:10:11.1536 - User action 2: timeUntilPreviousCallWillBeOrWasMade = 988.
19:10:11.1536 - User action 2: timeToWaitBeforeThisCallShouldBeMade = 1988.
19:10:11.1586 - User action 1: web service call.
19:10:11.1646 - User action 3: timeUntilPreviousCallWillBeOrWasMade = 990.
19:10:11.1646 - User action 3: timeToWaitBeforeThisCallShouldBeMade = 1990.
19:10:11.1756 - User action 4: timeUntilPreviousCallWillBeOrWasMade = 990.
19:10:11.1756 - User action 4: timeToWaitBeforeThisCallShouldBeMade = 1990.
19:10:11.1866 - User action 5: timeUntilPreviousCallWillBeOrWasMade = 990.
19:10:11.1866 - User action 5: timeToWaitBeforeThisCallShouldBeMade = 1990.
19:10:11.1976 - User action 6: timeUntilPreviousCallWillBeOrWasMade = 990.
19:10:11.1986 - User action 6: timeToWaitBeforeThisCallShouldBeMade = 1990.
19:10:11.2086 - User action 7: timeUntilPreviousCallWillBeOrWasMade = 990.
19:10:11.2086 - User action 7: timeToWaitBeforeThisCallShouldBeMade = 1990.
19:10:11.2186 - User action 8: timeUntilPreviousCallWillBeOrWasMade = 990.
19:10:11.2196 - User action 8: timeToWaitBeforeThisCallShouldBeMade = 1990.
19:10:11.2296 - User action 9: timeUntilPreviousCallWillBeOrWasMade = 990.
19:10:11.2296 - User action 9: timeToWaitBeforeThisCallShouldBeMade = 1990.
19:10:11.2406 - User action 10: timeUntilPreviousCallWillBeOrWasMade = 990.
19:10:11.2406 - User action 10: timeToWaitBeforeThisCallShouldBeMade = 1990.
19:10:13.1567 - User action 2: web service call.
19:10:13.1717 - User action 3: web service call.
19:10:13.1877 - User action 5: web service call.
19:10:13.1877 - User action 4: web service call.
19:10:13.2107 - User action 6: web service call.
19:10:13.2187 - User action 7: web service call.
19:10:13.2187 - User action 8: web service call.
19:10:13.2357 - User action 9: web service call.
19:10:13.2537 - User action 10: web service call.
你真的应该为工作使用正确的工具。SemaphoreSlim
怎么样?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ThrottledAsync
{
class Program
{
static void Main(string[] args)
{
// Queue up simultaneous calls.
MakeThrottledCall();
MakeThrottledCall();
MakeThrottledCall();
MakeThrottledCall();
Console.ReadLine();
}
// Used to throttle our web service calls.
// Max degree of parallelism: 1.
private static readonly SemaphoreSlim WebServiceMutex = new SemaphoreSlim(1, 1);
private static async void MakeThrottledCall()
{
// Wait for the previous call
// (and delay task) to complete.
await WebServiceMutex.WaitAsync();
try
{
await MakeCallToWebService();
// Report the completion of your web service call if necessary.
// Delay for a bit before releasing the semaphore.
await Task.Delay(1000);
}
finally
{
// Allow the next web service call to go through.
WebServiceMutex.Release();
}
}
private static async Task MakeCallToWebService()
{
// Simulate network delay.
await Task.Delay(new Random().Next(5, 10));
Console.WriteLine("WebServiceCall: {0:HH:mm:ss.ffff}", DateTime.Now);
}
}
}
编辑:MakeThrottledCall
不再返回Task
根据svick的评论
可以在msdn上使用Thread.Sleep(msecondtimeout)吗?
我建议你这样做