Мои функции очень быстро вернут информацию. это прекрасные новости! Тем не менее, поскольку параллельный цикл выполняется асинхронно, функция возвращает значение до его завершения, если только я не выполнил какое-либо долгосрочное задание в основном потоке, чтобы дождаться результата. Пользовательский интерфейс для удержания отсутствует, поэтому я использую async / await, чтобы получить быстрый результат в TPL.
Я ввел логическое значение флага и цикл while для ожидания результата.
это работает, но кажется странным.
Есть ли лучший способ «дождаться» результата в моей конкретной ситуации.
В первом фрагменте кода, когда я использую цикл while, все кажется странным.
Примечание: я должен упомянуть, что, поскольку это ответ Alexa, вне этой функции находится задача, которая «Task.Delays» в течение восьми секунд, а затем возвращает ответ, если моя другая задача занимает много времени, и Alexa собирается тайм-аут.
private static string SavedImageAnalysisResult(IReadOnlyCollection<Image> savedImageList, ConfigurationDto config)
{
string result = "[]";
BreakImageAnalysis = false;
if (!savedImageList.Any()) return result;
Parallel.ForEach(savedImageList, new ParallelOptions
{
MaxDegreeOfParallelism = 5000
},
async (image, loopState) =>
{
Task.Run(() => Console.Write("██"));
string threadLocalAnalysisResult =
await AnalyzeImageAsync(image.ImageBytes, config);
if (IsEmptyOrErrorAnalysis(threadLocalAnalysisResult)) return;
Task.Run(() => Console.Write("█ █"));
result = threadLocalAnalysisResult;
BreakImageAnalysis = true;
loopState.Break();
});
while (!BreakImageAnalysis) if (BreakImageAnalysis) break; //strange to do this?
return result;
}
Эта функция вызывается так:
public static List<Person> DetectPersonAsync()
{
Task.Run(() => Console.WriteLine("{0}\nNew Person Detection Requested...", DateTime.Now.ToString("f")));
ConfigurationDto config = Configuration.GetSettings();
camera = new SecurityCamera();
byte[] imageData = camera.GetImageAsByte(config.SecurityCameraUrl +
config.SecurityCameraStaticImage +
DateTime.Now);
if (!imageData.Any()) return null;
string imageAnalysis = "[]";
SavedImageList = camera.ImageCache;
Task.Run(() => Console.WriteLine("\nBegin Image Analysis...\n"));
var imageAnalysisTasks = new[]
{
Task.Factory.StartNew(() => SavedImageAnalysisResult(SavedImageList, config)),
Task.Factory.StartNew(() => InProgressImageAnalysisResult(camera, config))
};
Task.WaitAll(imageAnalysisTasks);
Task.Run(() => Console.WriteLine("\n\nAnalysis complete\n"));
if (!IsEmptyOrErrorAnalysis(imageAnalysisTasks[0].Result))
imageAnalysis = imageAnalysisTasks[0].Result;
if (!IsEmptyOrErrorAnalysis(imageAnalysisTasks[1].Result))
imageAnalysis = imageAnalysisTasks[1].Result;
return !IsEmptyOrErrorAnalysis(imageAnalysis)
? JsonConvert.DeserializeObject<List<Person>>(imageAnalysis)
: new List<Person>();
}
Но эта функция называется так:
if (alexa.IsLaunchRequest(alexaRequest))
{
//We don't want to wait for these two tasks to return
Task.Run(() => SendSecurityImageToMagicMirrorUi());
Task.Run(() => alexa.PostDirectiveResponseAsync(alexaRequest));
//On your marks get set go! 8 seconds and counting
return await Task.WhenAny(new[]
{
Task.Run(() => GetAlexaCognitiveResponseAsync()),
Task.Run(() => AlexaRequestTimeoutMonitor())
}).Result;
}
И, наконец, есть функция Timeout, которая будет возвращаться, если 8 секунд истекло:
private static async Task<object> AlexaRequestTimeoutMonitor()
{
await Task.Delay(new TimeSpan(0, 0, 0, 8));
return AlexaApi.ResponseBuilder(CreateNoPersonDetectionPhrase(new AlexaSynthesisResponseLibrary()), false);
}
Он находится в функции CreateNoPersonDetectedPhrase, в которой я возвращаю логический флаг IsFound обратно в «false»