我有一个调用 api 端点的脚本,但是当它发生奇怪的事情时,我什至无法解释它,所以我将向您展示代码并解释我得到的结果。
public class Program
{
private static OpenSeaApiClient openSeaApiClient;
private static Timer timer;
private static int counter = 1;
private static Collection galaxyEggs9999;
static async Task Main()
{
string apiKey = "myKey";
openSeaApiClient = new OpenSeaApiClient(apiKey);
// Set up a timer to run the API calls every 10 seconds
timer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);
timer.Elapsed += async (sender, e) => await TimerElapsedAsync();
timer.Start();
Console.WriteLine("Press Enter to exit.");
Console.ReadKey();
// Stop the timer when exiting the program
timer.Stop();
timer.Dispose();
}
private static async Task TimerElapsedAsync()
{
Console.WriteLine($"Counter: {counter++}");
if (galaxyEggs9999 == null)
{
galaxyEggs9999 = new Collection(openSeaApiClient, "galaxyeggs9999", "0xA08126f5E1ED91A635987071E6FF5EB2aEb67C48");
}
await galaxyEggs9999.ExecuteAsync();
//more instances
}
所以 TimerElapsedAsync() 是用一个 Timer 设置的。 当 TimerElapsedAsync() 启动时,会打印 1 并且脚本进入对象的第一个实例。这个物体看起来像这样:
public class Collection
{
private readonly OpenSeaApiClient openSeaApiClient;
private readonly string collectionName;
private readonly string collectionContractAddress;
public Collection(OpenSeaApiClient openSeaApiClient, string collectionName, string collectionContractAddress)
{
this.openSeaApiClient = openSeaApiClient;
this.collectionName = collectionName;
this.collectionContractAddress = collectionContractAddress;
}
public async Task ExecuteAsync()
{
//more code
}
else
{
var bestListingsResponse = await openSeaApiClient.GetBestListingsInCollectionResponse(CollectionName);
floorPriceInEtherDouble = GetCollectionFloorPriceInEther(bestListingsResponse);
//more code
问题来了——当脚本到达时
var bestListingsResponse = await openSeaApiClient.GetBestListingsInCollectionResponse(CollectionName);
2 被打印,之后是 3,4,5,然后脚本继续其他行。如果我在 GetBestListingsInCollectionResponse() 上放置一个断点并按 Step Over,它只会继续打印递增的数字,而不是继续。
如果这有帮助的话,这就是 GetBestListingsInCollectionResponse() 的样子。
public async Task<string> GetBestListingsInCollectionResponse(string collectionSlug)
{
string endpoint = $"api/v2/listings/collection/{collectionSlug}/best";
return await SendGetRequest(endpoint);
}
我的代码中有更多端点,它们都不断做奇怪的事情,比如多次执行自己。
为什么会出现这种情况?
System.Timers.Timer
,以及来自文档的备注部分:
组件是一个基于服务器的计时器,在Timer
属性中的毫秒数过去后,它会在应用程序中引发Elapsed
事件。您可以使用Interval
属性将Timer
对象配置为仅引发一次或重复引发事件。AutoReset
因此它不会等待处理程序完成,而是会在每次间隔过去时引发事件。
一种解决方法是将
AutoReset
设置为 false,然后在处理程序完成时启用计时器:
timer.AutoReset = false;
timer.Elapsed += (sender, eventArgs) =>
{
Thread.Sleep(1000); // simulate some work
Console.WriteLine("elapsed"); // simulate some work
timer.Enabled = true; // do not forget to handle the exceptions
};
System.Threading.PeriodicTimer
(例如在 ASP.NET Core 后台工作人员中利用它 - 参见此处)。