static async Task <int> MainAsync(string[] args)
        {
            //Log.WriteLine("pause...");
            //var x = Console.ReadLine();
            Log.WriteLine("Starting async...");
            Model            model      = null;
            AzureConnection  connection = null;
            MediaFrameReader reader     = null;
            EventWaitHandle  evtFrame   = null;

            await Task.WhenAll(
                Task.Run(async() =>
                         model = await Model.CreateModelAsync(
                             Directory.GetCurrentDirectory() + "\\resources\\office_fruit_coreml.onnx")),
                Task.Run(async() =>
                         connection = await AzureConnection.CreateAzureConnectionAsync()),
                Task.Run(async() => {
                (reader, evtFrame) = await GetFrameReaderAsync();
                await AsyncHelper.SyncFromAsync(reader.StartAsync(), "reader start");
            })
                );

            Log.WriteLine("Model loaded, Azure Connection created, and FrameReader Started\n\n\n\n");

            await CameraProcessingAsync(model, reader, evtFrame, connection);

            return(0);
        }
        public static async Task <AzureConnection> CreateAzureConnectionAsync()
        {
            var newConnection = new AzureConnection();
            await newConnection.AzureConnectionInitAsync();

            await newConnection._client.OpenAsync();

            Log.WriteLine("Azure connection Creation Complete");
            return(newConnection);
        }
        static async Task CameraProcessingAsync(Model model, MediaFrameReader reader, EventWaitHandle evtframe, AzureConnection azure)
        {
            var    fps_t0     = DateTime.Now;
            string prev_label = null;

            double fps = 0.0;

            for (UInt64 total_frame = 0, current_frame = 0; ; ++total_frame)
            {
                if (Model.Full)
                {
                    evtframe.WaitOne();
                    evtframe.Reset();
                }
                //auto input_feature{ImageFeatureValue::CreateFromVideoFrame(vf.get())};
                var frame = reader.TryAcquireLatestFrame();
                if (frame == null)
                {
                    // assume 60 fps, wait about half a frame for more input.
                    // in the unlikely event that eval is faster than capture this should be done differently
                    Thread.Sleep(10);
                    continue;
                }
                ++current_frame;
                //int oldFrame, double oldFps, DateTime oldFpsT0, string oldLabel)
                (current_frame, fps, fps_t0, prev_label) = await FrameProcessingAsync(model, frame, total_frame, current_frame, fps, fps_t0, prev_label, azure);
            }
        }
        static async Task <Tuple <UInt64, double, DateTime, string> > FrameProcessingAsync(Model model, MediaFrameReference frame, UInt64 totalFrame, UInt64 oldFrame, double oldFps, DateTime oldFpsT0, string oldLabel, AzureConnection azure)
        {
            UInt64   currentFrame  = oldFrame;
            double   fps           = oldFps;
            DateTime fpsT0         = oldFpsT0;
            string   prevLabel     = oldLabel;
            string   correlationId = String.Format("{0}", totalFrame);
            var      r             = await model.EvaluateAsync(frame, correlationId);

            if (!r._result.Succeeded)
            {
                Log.WriteLineUp3Home("eval failed {0}", r._result.ErrorStatus);
            }
            else
            {
                Log.WriteLineUp3Home("eval succeeded");
            }

            var fps_interval = DateTime.Now - fpsT0;

            if (fps_interval.Seconds > 10)
            {
                fps          = currentFrame * 1.0 / fps_interval.Seconds;
                currentFrame = 0;
                fpsT0        = DateTime.Now;
            }
            Log.WriteLineHome("fps {0}", fps.ToString("0.00"));


            string label = r._output.classLabel;
            var    most  = r.MostProbable;

            if (label != most.Key)
            {
                throw new ApplicationException(string.Format("Output Feature Inconsistency model output label 0 '{0}' and label 1 '{1}'", label, most.Key));
            }
            Log.WriteLine("{1}{2} with probability {3}", Log.fmt_output_success, most.Key, Log.fmt_output_default, most.Value.ToString("0.0000"));
            // we would like to apply a confidence threshold but with these models garbage always ends up high confidence something
            if (prevLabel == null || prevLabel != label)
            {
                prevLabel = label;
                azure.UpdateObject(label);
            }

            model.Clear(correlationId);
            return(new Tuple <UInt64, double, DateTime, string>(currentFrame, fps, fpsT0, prevLabel));
        }