在本地运行一次定时器触发的Azure功能的最简单方法是什么?

时间:2017-10-04 03:37:01

标签: c# azure timer azure-functions

我有一些使用https://www.khronos.org/opengl/wiki/Geometry_Shader按计划运行的C#Azure函数。我已经设置了它们,其中%TimerSchedule%指的是应用设置中的cron表达式:

public static void Run([TimerTrigger("%TimerSchedule%")]TimerInfo myTimer, TraceWriter log)

在开发过程中,我经常希望使用Azure功能工具为Visual Studio + Azure功能核心工具在本地运行这些功能。但是,当我按F5调试本地函数时,它(通常)不会立即运行。相反,它会根据计时器计划开始等待下一次出现。因此,例如,如果我的cron表达式说每天晚上8点运行,我必须等到晚上8点才能在我的机器上实际运行该功能。

所以我的问题是:在本地运行一次函数的最简单和最好的方法是什么?

我尝试或考虑过的事情:

  1. 使用更频繁的计时器计划仅用于本地开发
    • 这没关系但不完美 - 除非它非常频繁,否则你还需要等待一段时间,如果非常频繁,那么该功能可能会多次运行。这就是我现在正在做的事情。
  2. 编写直接调用函数Run()方法的控制台应用程序或单元测试
    • 这不是100%直截了当,因为您必须向TimerInfo提供TraceWriterRun()个参数 - 而且我发现这方面的文档很少。
  3. Microsoft的timer triggers页面对此主题不是很有帮助 - 它只提到计时器触发器作为测试其他触发器类型的方法。

    在一个完美的世界中,我点击F5并且该功能会立即运行一次 - 就像开发一个“普通”的.NET应用程序一样。

8 个答案:

答案 0 :(得分:43)

您也许可以使用RunOnStartup标记文件here。它没有完全符合你关于它只运行一次的简要说明,但它至少应该在应用程序启动后在本地执行它。

/// Gets or sets a value indicating whether the function should be invoked
/// immediately on startup. After the initial startup run, the function will
/// be run on schedule thereafter.

使用属性绑定的示例:

[TimerTrigger("%TimerSchedule%", RunOnStartup = true)]TimerInfo myTimer

答案 1 :(得分:24)

我有同样的问题,并且仅在调试时才使用DEBUG标志具有RunOnStartup:

        public static void Run(
            [TimerTrigger("* 0 7 * * 1-5"
#if DEBUG
            , RunOnStartup=true
#endif
            )]TimerInfo myTimer, TraceWriter log)
        {

答案 2 :(得分:8)

如果您使用的是VS Code,请使用Azure Functions extension

  1. 按F5进入调试模式,这将启动功能应用程序。
  2. 转到“活动”栏中的Azure图标。
  3. Local Project下,找到要运行的函数,右键单击,然后选择“立即执行函数”。

查看此MS quickstart guide

答案 3 :(得分:3)

我有同样的问题。我用Unittest修好了。 实际上,您需要存根TraceWriter和TimerInfo。

这里有一些代码我是如何做到这一点的。

TimerInfo:

public class ScheduleStub : TimerInfo
{
    public ScheduleStub(TimerSchedule schedule, ScheduleStatus status, bool isPastDue = false) : base(schedule, status, isPastDue)
    {
    }
}

TraceWriter:

 public class TraceWriterStub : TraceWriter
{
    protected TraceLevel _level;
    protected List<TraceEvent> _traces;

    public TraceWriterStub(TraceLevel level) : base(level)
    {
        _level = level;
        _traces = new List<TraceEvent>();
    }

    public override void Trace(TraceEvent traceEvent)
    {
        _traces.Add(traceEvent);
    }

    public List<TraceEvent> Traces => _traces;
}

答案 4 :(得分:3)

使用邮递员就可以解决问题。请按照以下步骤在本地运行或调试计时器触发器。

1。运行您的项目。

  1. 打开邮递员,并跳过该网址http://localhost:{port}/admin/functions/{function_name}

  2. 确保对Json正文使用POST方法 { “输入”:“” }

  3. 按SEND。

您应该收到202的回复。

答案 5 :(得分:1)

来自https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local#local-settings-file

  

非HTTP触发功能

     

对于HTTP触发器和Webhooks以外的所有其他功能,您可以通过调用管理端点在本地测试您的功能。在本地服务器上使用HTTP POST请求调用此端点将触发该功能。您可以选择将测试数据传递到POST请求正文中的执行中。此功能类似于Azure门户中的“测试”选项卡。

     

您调用以下管理员端点来触发非HTTP功能:

http://localhost:{port}/admin/functions/{function_name}

  

要将测试数据传递到功能的管理员端点,必须在POST请求消息的正文中提供数据。消息正文必须具有以下JSON格式:

{
    "input": "<trigger_input>"
}

答案 6 :(得分:1)

用这个 curl 命令启动你的函数

always_allow_html: true

输入数据是必须的,没有它,函数不会被触发。

答案 7 :(得分:0)

只需在同一类中添加具有HTTP触发类型的另一个函数,添加代码或从该函数调用Run方法并从浏览器中调用它即可。

在部署到产品时,请确保评论/删除该功能,否则您将能够通过产品中的HTTP调用来触发该功能。