multithreading - 如何将 Azure Durable Functions Orchestrator 中的逻辑移到另一个类中?

标签 multithreading async-await azure-functions azure-durable-functions

作为一般做法,我们一直在将自己的“服务”类注入(inject)到我们所有的功能应用程序中,并且我们希望为 Orchestrator 做同样的事情。

例子:

  public async Task<string> Run(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            try
            {
                // get input
                var input = context.GetInput<MyInputType>();

                // do some stuff #1

                var input1 = new BlahBlahOne();
                await context.CallActivityWithRetryAsync<string>("activityfn1", retryOptions, input1);

                // do some stuff #2

                var input1 = new BlahBlahTwo();
                await context.CallActivityWithRetryAsync<string>("activityfn3", retryOptions, input1);

                // do some stuff #3

                var input1 = new BlahBlahThree();
                await context.CallActivityWithRetryAsync<string>("activityfn3", retryOptions, input1);

                // do some stuff #4

                return "I'm done";
            }
            catch (Exception ex)
            {
                log.LogError(ex, "unexpected error");
                throw;
            }
        }

我们想做这样的事情:
  public async Task<string> Run(
            [OrchestrationTrigger] IDurableOrchestrationContext context,
            ILogger log)
        {
            try
            {
                string output = await _myOrchestratorService.RunAsync(context); // NOT allowed! 
                return output
            }
            catch (Exception ex)
            {
                log.LogError(ex, "unexpected error");
                throw;
            }
        }

但是,请注意,我们不能根据 Durable Functions 对多线程的代码限制使用“等待”。所以我在下面尝试了,但是我该如何编码呢?调用 .Result 会使代码在 Activity 函数上“挂起”。我究竟做错了什么?
public string Run(IDurableOrchestrationContext context)
{
       // code like before, but then how do I call this?
       // await context.CallActivityWithRetryAsync<string>("activityfn1", retryOptions, input1);

       // I tried this, doesn't work, will hang on the first activity function
       context.CallActivityWithRetryAsync<string>("activityfn1", retryOptions, input1).Result; 
}

最佳答案

澄清一下,使用 await 的限制在 Orchestrator 函数中仅适用于不是由 IDurableOrchestrationContext 生成的任务蜜蜂。引用 Durable Functions 编排code constraint documentation :

Orchestrator code must never start any async operation except by using the IDurableOrchestrationContext API or the context.df object's API. For example, you can't use Task.Run, Task.Delay, and HttpClient.SendAsync in .NET or setTimeout and setInterval in JavaScript. The Durable Task Framework runs orchestrator code on a single thread. It can't interact with any other threads that might be called by other async APIs.



this answer shows , 只调用 await 的异步辅助方法在 Task IDurableOrchestrationContext 创建的对象await 在技术上是安全的上为好。这意味着您调用 await _myOrchestratorService.RunAsync(context);可能没问题,只要该异步方法遵循所有正常的编排代码约束即可。

话虽如此,我并不完全确定通过注入(inject)一个似乎只有一个方法的服务可以获得什么,该方法包含通常存在于您的编排方法中的所有逻辑。这种抽象似乎并没有提高代码的可测试性,而且额外的抽象层可能会混淆我们的 Durable Functions 分析器,该分析器有助于诊断代码何时违反编排约束。

关于multithreading - 如何将 Azure Durable Functions Orchestrator 中的逻辑移到另一个类中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61731122/

相关文章:

c - 两个线程——从 STDIN 读取文本并通过管道发送

Java:在线程化时更改标签值

c++ - 具有 PPL 和并行内存分配的线程 ID

javascript - 异步/等待解析 json

f# - 在 F# 中使用 Task.WhenAll 重写 C# 代码

visual-studio - 从 Visual Studio 部署 Azure Function Slot 部署生产

c# - 我可以将 AsyncLocal 与 azure 函数一起使用吗?

c++ - 无锁数据结构中的非 POD 类型

c# - ASP.Net MVC4 beta - HttpClient 中没有await 关键字支持?

azure - 并行调用数百个 azure 函数