public async Task <GeneralOcrResult> MatchOnCloudAsync(
            string cloudEndpoint,
            string cloudApiKey,
            DeviceOcrResult deviceOcrResult,
            TimeSpan timeBetweenCalls,
            TimeSpan timeout)
        {
            GeneralOcrResult ocrResult = new GeneralOcrResult()
            {
                ResultType = OcrMatchResult.CloudCallFailed
            };

            if (deviceOcrResult.ResultType != OcrMatchResult.TimedOutCloudCallAvailable)
            {
                throw new InvalidOperationException();
            }
            var resultLocation = await SubmitBitmapToCloudGetResultLocationAsync(
                cloudEndpoint, cloudApiKey, deviceOcrResult);

            if (!string.IsNullOrEmpty(resultLocation))
            {
                ocrResult = await PollCloudResultLocation(resultLocation, cloudApiKey, timeBetweenCalls, timeout);
            }
            return(ocrResult);
        }
        async Task <GeneralOcrResult> PollCloudResultLocation(
            string operationLocationUri,
            string cloudApiKey,
            TimeSpan timeBetweenCalls,
            TimeSpan timeout)
        {
            GeneralOcrResult result = new GeneralOcrResult()
            {
                ResultType = OcrMatchResult.CloudCallTimedOut
            };
            var delayTask = Task.Delay(timeout);

            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders[API_SUBSCRIPTION_KEY_HEADER] = cloudApiKey;
                bool continuePolling = true;

                while (!delayTask.IsCompleted && continuePolling)
                {
                    // Note - some sort of delay between polling calls might be nice? :-)
                    var response = await httpClient.GetAsync(new Uri(operationLocationUri));

                    // Note that this API can return 'too many requests' and ask you to re-call
                    // in a number of seconds. Not sure what to do on that front.
                    if (response.IsSuccessStatusCode)
                    {
                        var jsonResponse = await response.Content.ReadAsStringAsync();

                        var jsonObject = JsonObject.Parse(jsonResponse);

                        switch (jsonObject[JSON_STATUS_VALUE].GetString())
                        {
                        case RECOGNITION_API_SUCCEEDED:
                            continuePolling    = false;
                            result.MatchedText = this.ParseRecognitionServiceResponseForMatch(jsonObject);
                            result.ResultType  =
                                string.IsNullOrEmpty(result.MatchedText) ? OcrMatchResult.CloudCallProducedNoMatch : OcrMatchResult.Succeeded;
                            break;

                        case RECOGNITION_API_RUNNING:
                        case RECOGNITION_API_NOT_STARTED:
                            break;

                        case RECOGNITION_API_FAILED:
                            result.ResultType = OcrMatchResult.CloudCallFailed;
                            break;

                        default:
                            break;
                        }
                    }
                    await Task.Delay(timeBetweenCalls);
                }
            }
            return(result);
        }