1

我有一个 Azure 函数,它能够调用多个 API 端点,而无需等待其中任何一个端点的结果。

Azure 函数在计时器触发器上运行,每 10 秒运行一次。

我所有的 API 调用和调用它们的参数都存储在一个 SQL 表中。我想确保在不等待特定调用完成的情况下进行 API 调用。

这只是我将要做的事情的蓝图。

[FunctionName("FunctionScheduler")]
public static async Task RunAsync([TimerTrigger("*/10 * * * * *")]TimerInfo myTimer, ILogger log)
{
    log.LogInformation("FUNCTION SCHEDULER STARTING ..");

    log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

    for(int i=0; i < 20; i++)
    {
        var task = Task.Run(() => ApiRef1(i, log));
        var taskref = await task;
    }

}

目前 ApiRef1() 只是打印出变量 i 的值。我得到了打印数字 0 到 19 的预期输出。我希望并行执行 ApiRef1() 方法,该方法最终将被类似这样的方法替换。

private static void CallApi(string apiName, string apiEndpoint, string methodType, string authenticationType, IDictionary<int, string> parameters, ILogger log)
{
    try
    {
        log.LogInformation($"Call to API {apiName} started.." );

        // Call API
    }
    catch (Exception ex)
    {
        log.LogInformation($"Exception {ex.Message} occurred.." );
    }
}

有没有更好的方法来做到这一点,或者这种方法会奏效吗?

4

3 回答 3

2

当您使用 Azure 函数时,您不能真正着火并忘记,因为您冒着函数在所有任务完成之前终止的风险。

但是,我们不关心任务的结果,所以我们不需要单独等待每个任务。

System.Collections.Generic.List<System.Threading.Tasks.Task> tasks = new System.Collections.Generic.List<System.Threading.Tasks.Task>();
for (int i = 0; i < 20; i++)
{
  tasks.Add(System.Threading.Tasks.Task.Run(() => ApiRef1(i, log));
}
await System.Threading.Tasks.Task.WhenAll(tasks);

这允许所有任务并行触发,但暂停进一步执行直到它们全部完成,确保在进程终止之前完成任务。

于 2019-10-29T15:21:44.620 回答
1

Task.Run()返回一个Task。当您“解雇并忘记”时,您就不会关心该任务。

要接受DetectivePikachu的建议,请使用丢弃以确保您不关心结果。

public void Run()
{
    ...

    _ = Task.Run(() => ApiRef1(i, log));

    ...
}

包含Task.Run调用的方法本身不是异步的。除非您有其他方法调用 using await,否则您不再需要 async 。

于 2019-10-29T14:59:49.150 回答
1

您可以使用 async/Task 功能。这是一个例子

    public static class AzureFunction
    {
        [FunctionName("SomeAzureFunction")]
        public static void Run([TimerTrigger("*/10 * * * * *")]TimerInfo myTimer, ILogger log)
        {
            Function1(log);
            Function2(log);
            Function3(log);
        }

        private static async void Function1(ILogger log)
        {
            await Task.Run(() =>
            {
                Thread.Sleep(6000);
                log.LogInformation("Function 1 now executed");
            });
        }

        private static async void Function2(ILogger log)
        {
            await Task.Run(() =>
            {
                Thread.Sleep(2000);
                log.LogInformation("Function 2 now executed");
            });
        }

        private static async void Function3(ILogger log)
        {
            await Task.Run(() =>
            {
                log.LogInformation("Function 3 now executed");
            });
        }
    }

(Threat.Sleep() 行仅用于向您展示函数如何/如何相互独立地执行)

在输出窗口中,您将看到所有三个函数都已启动,但函数 3 将首先完成(因为我们没有使线程休眠),然后函数 2 将完成(因为我们有 2 秒的延迟),最后函数 1 将完成(延迟 6 秒)。

请注意,此示例中的所有函数都有一个返回类型“Void”。因此,此示例仅在您不关心函数的任何返回值时才有效。

但我认为这接近你要求的

于 2019-10-29T15:08:21.763 回答