Alan2
Alan2

Reputation: 24572

How can I cancel a Device.BeginInvokeOnMainThread()?

I have this code:

Device.BeginInvokeOnMainThread(() => Show().ContinueWith((arg) => { }));

public async Task Show()
{
   while (true)
   {
      await Task.Delay(500);
      Debug.WriteLine("test1");
      while (true)
      {
         await Task.Delay(500);
         Debug.WriteLine("test2");
      }
   }
}

I know if I have a task that I can cancel it but for this code. How can I cancel the execution of Show() if for example it was running in a loop and I wanted to cancel from outside of that method?

Note that I added

.ContinueWith((arg)

As it stops my IDE from giving an error.

For reference here's the class for DEVICE from Xamarin

public static class Device
{
    //
    // Static Fields
    //
    public const string iOS = "iOS";

    public const string Android = "Android";

    public const string WinPhone = "WinPhone";

    public const string UWP = "UWP";

    public const string WinRT = "WinRT";

    public const string macOS = "macOS";

    [EditorBrowsable (EditorBrowsableState.Never)]
    public static DeviceInfo info;

    private static IPlatformServices s_platformServices;

    //
    // Static Properties
    //
    [EditorBrowsable (EditorBrowsableState.Never)]
    public static IReadOnlyList<string> Flags {
        [CompilerGenerated]
        get;
        [CompilerGenerated]
        private set;
    }

    public static TargetIdiom Idiom {
        [CompilerGenerated]
        get;
        [CompilerGenerated]
        internal set;
    }

    [EditorBrowsable (EditorBrowsableState.Never)]
    public static DeviceInfo Info {
        get;
        set;
    }

    [EditorBrowsable (EditorBrowsableState.Never)]
    public static bool IsInvokeRequired {
        get;
    }

    [Obsolete ("TargetPlatform is obsolete as of version 2.3.4. Please use RuntimePlatform instead.")]
    public static TargetPlatform OS {
        get;
    }

    [EditorBrowsable (EditorBrowsableState.Never)]
    public static IPlatformServices PlatformServices {
        get;
        set;
    }

    public static string RuntimePlatform {
        get;
    }

    //
    // Static Methods
    //
    public static void BeginInvokeOnMainThread (Action action);

    [EditorBrowsable (EditorBrowsableState.Never)]
    public static Assembly[] GetAssemblies ();

    [EditorBrowsable (EditorBrowsableState.Never)]
    public static double GetNamedSize (NamedSize size, Type targetElementType, bool useOldSizes);

    public static double GetNamedSize (NamedSize size, Element targetElement);

    public static double GetNamedSize (NamedSize size, Type targetElementType);

    internal static Task<Stream> GetStreamAsync (Uri uri, CancellationToken cancellationToken);

    [Obsolete ("OnPlatform is obsolete as of version 2.3.4. Please use switch(RuntimePlatform) instead.")]
    public static void OnPlatform (Action iOS = null, Action Android = null, Action WinPhone = null, Action Default = null);

    [Obsolete ("OnPlatform<> (generic) is obsolete as of version 2.3.4. Please use switch(RuntimePlatform) instead.")]
    public static T OnPlatform<T> (T iOS, T Android, T WinPhone);

    public static void OpenUri (Uri uri);

    [EditorBrowsable (EditorBrowsableState.Never)]
    public static void SetFlags (IReadOnlyList<string> flags);

    [EditorBrowsable (EditorBrowsableState.Never)]
    public static void SetIdiom (TargetIdiom value);

    [EditorBrowsable (EditorBrowsableState.Never)]
    public static void SetTargetIdiom (TargetIdiom value);

    public static void StartTimer (TimeSpan interval, Func<bool> callback);

    //
    // Nested Types
    //
    public static class Styles
    {
        public static readonly string TitleStyleKey;

        public static readonly string SubtitleStyleKey;

        public static readonly string BodyStyleKey;

        public static readonly string ListItemTextStyleKey;

        public static readonly string ListItemDetailTextStyleKey;

        public static readonly string CaptionStyleKey;

        public static readonly Style TitleStyle;

        public static readonly Style SubtitleStyle;

        public static readonly Style BodyStyle;

        public static readonly Style ListItemTextStyle;

        public static readonly Style ListItemDetailTextStyle;

        public static readonly Style CaptionStyle;
    }
}

Upvotes: 1

Views: 915

Answers (1)

zc246
zc246

Reputation: 1514

It's not really related to Device, but how to cancel an Action.

You would use CancellationTokenSource. (Since it's in Xamarin's doc, I believe it's available for you to use)

private CancellationTokenSource _cts;

void Handler1()
{
    _cts = new CancellationTokenSource();
    Device.BeginInvokeOnMainThread(() => Show(_cts.Token).ContinueWith((arg) => { }));
}

void Handler2()
{
    if (_cts != null)
    {
        _cts.Cancel(); // <---- Cancel here
    }
}

public async Task Show(CancellationToken ct)
{
    while (true)
    {
        await Task.Delay(500, ct); // <-- Thanks to @Evk's suggestion
        Debug.WriteLine("test1");

        if (ct.IsCancellationRequested)
        {
            // another thread decided to cancel
            Console.WriteLine("Show canceled");
            break;
        }
    }
}

Reference post: https://stackoverflow.com/a/4783890/2710486

Upvotes: 2

Related Questions