【问题标题】:Using an Async method in a Azure Fuction Servicebus trigger在 Azure 函数服务总线触发器中使用异步方法
【发布时间】:2019-07-26 19:21:53
【问题描述】:

我正在使用队列存储、blob 存储和带有队列触发器的 Azure 函数制作项目。它包括在队列接收消息的任何时候,在 blob 中拍摄具有相同名称的图片,然后使用 FaceApi 进行分析,在 Json 中发送 ServiceBus 主题。程序是异步的。

public static async Task<string> MakeAnalysisRequestAsync()
string valor = "";
            const string subscriptionKey = "yoursubsciptionkey";


            const string uriBase =
                "https://westeurope.api.cognitive.microsoft.com/face/v1.0/detect";

            HttpClient client = new HttpClient();

            // Request headers.
            client.DefaultRequestHeaders.Add(
                "Ocp-Apim-Subscription-Key", subscriptionKey);

            // Request parameters. A third optional parameter is "details".
            string requestParameters = "returnFaceId=true&returnFaceLandmarks=false" +
                "&returnFaceAttributes=age,gender,headPose,smile,facialHair,glasses," +
                "emotion,hair,makeup,occlusion,accessories,blur,exposure,noise";

            // Assemble the URI for the REST API Call.
            string uri = uriBase + "?" + requestParameters;

            HttpResponseMessage response;

            //forearch element in yourqueue, search in blob storage and make an analysis
            CloudStorageAccount storageAccount = new CloudStorageAccount(
new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
"yourstorage",
"connectionstorage"), true);

            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer container = blobClient.GetContainerReference("yourstorage");



            // Create the queue client
            CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();

            // Retrieve a reference to a queue
            CloudQueue queue = queueClient.GetQueueReference("yourqueue");

            // Get the next message
            CloudQueueMessage retrievedMessage = await queue.GetMessageAsync();

            string prueba = retrievedMessage.AsString;
            CloudBlockBlob blockBlob = container.GetBlockBlobReference(prueba);

            var uriblob = blockBlob.Uri.AbsoluteUri;
            var webClient = new WebClient();
            byte[] imageBytesuri = webClient.DownloadData(uriblob);


            using (ByteArrayContent content = new ByteArrayContent(imageBytesuri))
            {

                content.Headers.ContentType =
                    new MediaTypeHeaderValue("application/octet-stream");

                // Execute the REST API call.
                response = await client.PostAsync(uri, content);

                // Get the JSON response.
                string contentString = await response.Content.ReadAsStringAsync();
                valor = contentString;

            }
            return valor;
} 





它可以正常工作,例如如果队列中有一条名为 Darren.png 的消息,它将返回 blob 存储中图片 Darren.png 的人脸分析,如下所示

[{"faceId":"45 345345435","faceRectangle":{"top":84,"left":98,"width":83,"height":83},"faceAttributes":{"smile":1.0,"headPose":{"pitch":-11.3,"roll":8.4,"yaw":-9.4},"gender":"male","age":48.0,"facialHair":{"moustache":0.1,"beard":0.1,"sideburns":0.1},"glasses":"NoGlasses","emotion":{"anger":0.0,"contempt":0.0,"disgust":0.0,"fear":0.0,"happiness":1.0,"neutral":0.0,"sadness":0.0,"surprise":0.0},"blur":{"blurLevel":"low","value":0.0},"exposure":{"exposureLevel":"overExposure","value":0.83},"noise":{"noiseLevel":"low","value":0.08},"makeup":{"eyeMakeup":false,"lipMakeup":false},"accessories":[],"occlusion":{"foreheadOccluded":false,"eyeOccluded":false,"mouthOccluded":false},"hair":{"bald":0.13,"invisible":false,"hairColor":[{"color":"brown","confidence":1.0},{"color":"red","confidence":0.66},{"color":"blond","confidence":0.25},{"color":"black","confidence":0.16},{"color":"gray","confidence":0.13},{"color":"other","confidence":0.03}]}}}]

现在,我创建了一个带有队列触发器的 AzureFunction,并加载了分析程序“faceApiCorregido”。

[FunctionName("Function1")]
        public static void Run([QueueTrigger("yourqueue", Connection = "AzureWebJobsStorage")]string myQueueItem, TraceWriter log)
        {
           string messageBody =  Funciones.MakeAnalysisRequestAsync().ToString();

            //Task<string> messageBody2 =  Funciones.MakeAnalysisRequestAsync();
            //string messageBody1 = await messageBody.GetResult();
            log.Info($"C# Queue trigger function processed: {myQueueItem}");
            const string ServiceBusConnectionString = "yourconnectionstring";
            const string TopicName = "topicfoto";
            ITopicClient topicClient;
            topicClient = new TopicClient(ServiceBusConnectionString, TopicName);

            // Create a new message to send to the topic
            //string messageBody =  FaceApiLibreriaCoreFoto.Funciones.MakeAnalysisRequestAsync().ToString();

           // string messageBody = FaceApiCorregido.Funciones.MakeAnalysisRequestAsync().ToString(); 
            var message = new Message(Encoding.UTF8.GetBytes(messageBody));

            // Write the body of the message to the console
            Console.WriteLine($"Sending message: {messageBody}");

            // Send the message to the topic
             topicClient.SendAsync(message);


        }

但它不起作用,我需要一个字符串而不是一个任务。我尝试了不同的方法来修复它,但它不起作用,例如,如果我写了

string messageBody =  Funciones.MakeAnalysisRequestAsync().ToString();

它会返回类似的东西

System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.String,FaceApiCorregido.Funciones+<MakeAnalysisRequestAsync>d__1]

我也尝试过 getResult().getAwaiter() 但我有错误。最后我尝试让我的 AzureFunction 异步,但也给了我一个类似 System.Private.CoreLib 的错误:执行函数时出现异常:Function1。 FaceApiCorregido:对象引用未设置为对象的实例。 我知道这是一个常见问题,并且有很多信息可以解决它,但我不知道如何解决。有人能帮帮我吗? 谢谢你。

【问题讨论】:

  • 可以显示异步函数代码吗?
  • 对不起,我刚做了。

标签: c# string azure task azure-functions


【解决方案1】:

如果您希望它同步运行,只需调用

string messageBody =  Funciones.MakeAnalysisRequestAsync().Result;

如果异步:

string messageBody =  await Funciones.MakeAnalysisRequestAsync();

异步方法不直接返回结果。它们返回一个 Task ,您必须等待它完成,或者通过 await 关键字等待它完成,该关键字将释放当前线程并在任务完成后恢复,或者仅调用 result 将阻塞当前执行,直到结果可用。

【讨论】:

  • 感谢您的建议,但在这两种情况下,它都会返回相同的问题 System.Private.CoreLib:执行函数时出现异常:Function1。 System.Private.CoreLib:出现一个或多个错误。 (你调用的对象是空的。)。 FaceApiCorregido:对象引用未设置为对象的实例。但是,当我写字符串 messageBody = Funciones.MakeAnalysisRequestAsync().ToString();。它发送 System.Runtime.CompilerServices.AsyncTaskMethodBuilder1+AsyncStateMachineBox1[System.String,FaceApiCorregido.Funciones+d__1].
  • 当您执行 Funciones.MakeAnalysisRequestAsync().ToString(); 时,您将 ToString 应用于任务,而不是结果。这导致System.Runtime.CompilerServices.AsyncTaskMethodBuilder1+AsyncStateMachineBox1[System.String,FaceApiCorregido.Funciones+&lt;MakeAnalysisRequestAsync&gt;d__1].
  • 您的问题出在您的 Async 函数内部,而不是您调用它的方式。我的任何一个建议都会奏效。
  • 在这种情况下,我没有发现问题,让我解释一下我在控制台项目(FaceApiCorregido)中使用异步方法,并且没有问题。
  • 查看您的代码时,很明显您对 Task 有一些不理解的地方。你开始他们,但从不等待结果。例如,您必须等待 topic.SendAsync(message).Wait()await。试试docs.microsoft.com/en-en/dotnet/csharp/programming-guide/…
猜你喜欢
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-01
  • 2021-11-21
  • 2023-02-14
  • 2020-05-03
  • 1970-01-01
相关资源
最近更新 更多