c# - 在 Azure Fuction Servicebus 触发器中使用异步方法
问题描述
我正在使用队列存储、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:对象引用未设置为对象的实例。我知道这是一个常见问题,并且有很多信息可以解决它,但我不知道如何解决。有人能帮帮我吗?谢谢你的好处。
解决方案
如果您希望它同步运行,只需调用
string messageBody = Funciones.MakeAnalysisRequestAsync().Result;
如果异步:
string messageBody = await Funciones.MakeAnalysisRequestAsync();
异步方法不直接返回结果。他们返回一个 Task ,你必须等待它通过 await 关键字完成,这将释放当前线程并在任务完成后恢复,或者只调用 result ,这将阻止当前执行,直到结果可用。
推荐阅读
- php - 用 php 创建表
- r - 查找满足多个条件的行,返回不同的列,用于完整数据集
- pytorch - volatile 已被删除,现在使用 with.torch.no_grad() instread 无效
- c# - 获取网络元素内的随机点
- javascript - 使用 Object.keys 在构造函数中初始化值时是否存在对象污染?
- html2canvas - 如何提高 RecordRTC 中 CanvasRecorder 的分辨率和质量?
- python - 如何使用 Pyspark 从 CSV 中正确读取 JSON 字符串?
- python - 绘图的过滤条件
- python - Python 真正基础的 For 循环问题。为什么它永远循环?
- wpf - WPF MVVM Combobox SelectionChanged 刚刚重新加载 ViewModel