0
votes

I'm currently creating an app with Xamarin in combination with oxyplot. My plot is visible on the main app page and whenever I close my app, it crashes with the following message:

Unhandled Exception:

System.ObjectDisposedException: Cannot access a disposed object. Object name: 'OxyPlot.Xamarin.Android.PlotView'.

Please note that this is a known bug in the oxyplot-xamarin package. Now, I'm trying to work around this issue with no success so far. The critical part of my code looks as follows:

private void OnTimerElapsed(object state)
{
    lock (Model.SyncRoot)
    {
        Update();
    }
    try {
        Device.BeginInvokeOnMainThread(() => Model.InvalidatePlot(true)); // this line crashes the app
    } catch {
    }
}

I would like to ask within this periodically called function whether the app is still alive or whether it has already been closed. Thus, the solution would have to look like something along those lines:

private void OnTimerElapsed(object state)
{
    lock (Model.SyncRoot)
    {
        Update();
    }
    try {
        if (AppIsNotClosed)
        {
             Device.BeginInvokeOnMainThread(() => Model.InvalidatePlot(true)); // this line crashes the app
        }
    } catch {
    }
}

Any ideas how to check for the state of the app in Xamarin? Thank you very much!

1
Thank you very much for your comment @SushiHangover but I know about the Activity lifecycle already. However, I fail to see how this knowledge helps me to solve the problem stated above.Hagbard
Because it tells you that OnPause is called when that activity leaves the foreground and thus it is when you should stop your timer and then in OnResume you can start/re-start it...SushiHangover

1 Answers

0
votes

Thanks to the comments from @SushiHangover I now came up with the solution given below. My App.xaml.cs now looks as follows:

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace MyNamespace
{
    public partial class App : Application
    {
        private static bool AppIsActive = false;

        public App()
        {
            // InitializeComponent();
        }

        protected override void OnStart()
        {
            // Handle when your app starts
            AppIsActive = true;
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
            AppIsActive = false;
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
            AppIsActive = true;
        }

        public static bool IsAppActive()
        {
            return AppIsActive;
        }
    }
}

Then, the method in question can be rewritten as follows:

private void OnTimerElapsed(object state)
{
    lock (Model.SyncRoot)
    {
        Update();
    }
    try {
        if (App.IsAppActive()) {
            Device.BeginInvokeOnMainThread(() => Model.InvalidatePlot(true));
        } else {
            timer.Dispose();
        }
    } catch {
    }
}