Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception on Long-Running Analyze Method in BarcodeAnalyzer #219

Open
sylac opened this issue Dec 16, 2023 · 0 comments
Open

Exception on Long-Running Analyze Method in BarcodeAnalyzer #219

sylac opened this issue Dec 16, 2023 · 0 comments
Labels
bug Something isn't working

Comments

@sylac
Copy link

sylac commented Dec 16, 2023

Describe the bug
When the Analyze method in BarcodeAnalyzer runs for an extended period, it throws a Cannot access a disposed object exception. This issue seems to occur due to the asynchronous nature of the method, particularly when processing images for OCR or barcode scanning.

To Reproduce
Steps to reproduce the behavior:
Ensure the method is running for a prolonged duration, ideally in a scenario with continuous image processing.

  1. Refactor BarcodeAnalyzer:
public async void Analyze(IImageProxy proxy)
{
    try
    {
        var mediaImage = proxy.Image;
        if (mediaImage == null) return;

        _lastRunTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();

        if (_lastRunTime - _lastAnalysisTime > _cameraView.ScanInterval && _cameraView.IsScanning)
        {
            _lastAnalysisTime = _lastRunTime;
            var image = InputImage.FromMediaImage(mediaImage, proxy.ImageInfo.RotationDegrees);

            OCRResult ocrFinalResult = null;

            // Pass image to the scanner and have it do its thing
            using (var textScanner = TextRecognition.GetClient(Xamarin.Google.MLKit.Vision.Text.Latin.TextRecognizerOptions.DefaultOptions))
            {
                var ocrResult = await ToAwaitableTask(textScanner.Process(image));
                ocrFinalResult = OCRMethods.ProcessOCRResult(ocrResult);
            }

            if (!_cameraView.IsScanning)
                return;

            Log.Debug($"{nameof(BarcodeAnalyzer)}",
                $"""
                OCR: {ocrFinalResult?.AllText}
                """);
        }
    }
    catch (Java.Lang.Exception ex)
    {
        Log.Debug(nameof(BarcodeAnalyzer), ex.ToString());
    }
    catch (Exception ex)
    {
        Log.Debug(nameof(BarcodeAnalyzer), ex.ToString());
    }
    finally
    {
        SafeCloseImageProxy(proxy);
    }
}
  1. add logs in SafeCloseImageProxy catch block:
private void SafeCloseImageProxy(IImageProxy proxy)
{
    try
    {
        proxy?.Close();
    }
    catch (Exception exeption)
    {
        Log.Debug(nameof(BarcodeAnalyzer), exeption.ToString());
    }
}
  1. Observe the application for any exceptions thrown during the execution.
  2. The Cannot access a disposed object exception should occur after some time.

Expected behavior
The Analyze method is expected to process images continuously without throwing exceptions related to disposed objects. The method should handle long-running operations and resource management efficiently.

Screenshots
If applicable, add screenshots to help explain your problem.

Smartphone (please complete the following information):

  • Device: Samsung A52 & A53
  • OS: Android 13 & 14
  • Version MAUI .NET8

Additional context / Solution
The issue seems to be linked to the asynchronous execution pattern in the Analyze method. A potential solution involves refactoring the method for synchronous execution, which could prevent the disposal of objects that are still in use. This refactoring would involve removing the async keyword and managing tasks and resources in a synchronous context.
Refactoring Analyze method like this seems to solve the issue:

 public void Analyze(IImageProxy proxy)
{
    try
    {
        var mediaImage = proxy.Image;
        if (mediaImage == null) return;

        _lastRunTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();

        if (_lastRunTime - _lastAnalysisTime > _cameraView.ScanInterval && _cameraView.IsScanning)
        {
            _lastAnalysisTime = _lastRunTime;
            var image = InputImage.FromMediaImage(mediaImage, proxy.ImageInfo.RotationDegrees);

            List<BarcodeResult> barcodeFinalResult = null;
            OCRResult ocrFinalResult = null;

            // Pass image to the scanner and have it do its thing
            if (_cameraView.IsOCR)
            {
                using (var textScanner = TextRecognition.GetClient(Xamarin.Google.MLKit.Vision.Text.Latin.TextRecognizerOptions.DefaultOptions))
                {
                    var ocrTask = ToAwaitableTask(textScanner.Process(image));
                    ocrTask.Wait();
                    ocrFinalResult = OCRMethods.ProcessOCRResult(ocrTask.Result);
                }
            }
            else
            {
                var barcodeTask = ToAwaitableTask(_barcodeScanner.Process(image));
                barcodeTask.Wait();
                barcodeFinalResult = Methods.ProcessBarcodeResult(barcodeTask.Result);
                if (barcodeFinalResult == null || _cameraView == null) return;
            }

            if (!_cameraView.IsScanning)
                return;

            var imageData = Array.Empty<byte>();
            if (_cameraView.ReturnBarcodeImage)
            {
                imageData = NV21toJPEG(YUV_420_888toNV21(mediaImage), mediaImage.Width, mediaImage.Height);
                imageData = RotateJpeg(imageData, GetImageRotationCorrectionDegrees());
            }

            _cameraView.IsScanning = false;
            _cameraView.TriggerOnDetected(ocrFinalResult, barcodeFinalResult, imageData);
            if (_cameraView.VibrationOnDetected)
                Vibration.Vibrate(200);
        }
    }
    catch (Java.Lang.Exception ex)
    {
        Log.Debug(nameof(BarcodeAnalyzer), ex.ToString());
    }
    catch (Exception ex)
    {
        Log.Debug(nameof(BarcodeAnalyzer), ex.ToString());
    }
    finally
    {
        SafeCloseImageProxy(proxy);
    }
}
@sylac sylac added the bug Something isn't working label Dec 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant