Bug 4040 - System.ArgumentException when inheriting AsyncTask<,,> and overriding RunInBackground but not DoInBackground
Summary: System.ArgumentException when inheriting AsyncTask<,,> and overriding RunInBa...
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: BCL Class Libraries ()
Version: 4.0
Hardware: PC Mac OS
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2012-03-22 17:25 UTC by Jonathan Pryor
Modified: 2012-03-23 16:10 UTC (History)
2 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Jonathan Pryor 2012-03-22 17:25:55 UTC
Email thread:

    http://lists.ximian.com/pipermail/monodroid/2012-March/009408.html

Repro: Consider the following app:


  using System;

  using Android.App;
  using Android.Content;
  using Android.Runtime;
  using Android.Views;
  using Android.Widget;
  using Android.OS;

  namespace Scratch.AsyncTask
  {
    [Activity (Label = "Scratch.AsyncTask", MainLauncher = true)]
    public class Activity1 : Activity
    {
      int count = 1;

      protected override void OnCreate (Bundle bundle)
      {
        base.OnCreate (bundle);

        // Set our view from the "main" layout resource
        SetContentView (Resource.Layout.Main);

        // Get our button from the layout resource,
        // and attach an event to it
        Button button = FindViewById<Button> (Resource.Id.myButton);
        
        button.Click += delegate {
          button.Text = string.Format ("{0} clicks!", count++); };
        
        new MyAsyncTask ().Execute ("a", "b");
      }
    }
    
    class MyAsyncTask : AsyncTask<string, string, string> {
      protected override string RunInBackground (params string[] @params)
      {
        Console.WriteLine ("RunInBackground: params={0}",
            string.Join ("; ", @params));
        return "";
      }
      
      protected override Java.Lang.Object DoInBackground (
          params Java.Lang.Object[] native_parms)
      {
        return base.DoInBackground (native_parms);
      }
      
      protected override void OnPostExecute (string result)
      {
        Console.WriteLine ("OnPostExecute: result={0}", result);
      }
    }
  }

Build, then install and run on device as a Release build.

Result:

E/mono    ( 4934): Unhandled Exception: System.ArgumentException: Couldn't bind to method 'GetDoInBackground_arrayLjava_lang_Object_Handler'.
E/mono    ( 4934):   at System.Delegate.GetCandidateMethod (System.Type type, System.Type target, System.String method, BindingFlags bflags, Boolean ignoreCase, Boolean throwOnBindFailure) [0x00000] in <filename unknown>:0 
E/mono    ( 4934):   at System.Delegate.CreateDelegate (System.Type type, System.Type target, System.String method, Boolean ignoreCase, Boolean throwOnBindFailure) [0x00000] in <filename unknown>:0 
E/mono    ( 4934):   at System.Delegate.CreateDelegate (System.Type type, System.Type target, System.String method) [0x00000] in <filename unknown>:0 
E/mono    ( 4934):   at Android.Runtime.JNIEnv.RegisterJniNatives (IntPtr typeName_ptr, Int32 typeName_len, IntPtr jniClass, IntPtr methods_ptr, Int32 methods_len) [0x00000] in <filename unknown>:0 
E/mono    ( 4934):   at (wrapper delegate-invoke) <Module>:invoke_intptr__this___intptr_intptr_string_string (intptr,intptr,string,string)
Comment 1 Jonathan Pryor 2012-03-22 17:26:41 UTC
Er...

Edit the above sample and remove MyAsyncTask.DoInBackground().

THEN it'll fail.

Adding in DoInBackground() is the workaround.
Comment 2 Jonathan Pryor 2012-03-22 17:27:58 UTC
The reason it fails is because the linker doesn't realize that we're "aliasing" DoInBackground() with RunInBackground(). Since DoInBackground() isn't overridden, it isn't preserved, and thus the helper GetDoInBackground_arrayLjava_lang_Object_Handler isn't preserved either.

The workaround is to override DoInBackground() so that the helper is preserved, thus allowing RunInBackground() to work.
Comment 3 Jonathan Pobst 2012-03-23 16:10:22 UTC
Fixed for 4.2.

70b4d98ebae330663cd5ea6a19888058ea708bab