I've moved to something a bit simpler that, from initial tests anyways, appears 
to work.  Does this seem reasonable though (I think it assumes that the 
UIInvoker class itself is created on the UI thread):

    public class UIInvoker : DisposableBase
    {
        private Activity m_activity = new Activity();

        public void Invoke(Delegate method)
        {
            m_activity.RunOnUiThread(delegate
            {
                method.DynamicInvoke(null);
            });
        }

        public void BeginInvoke(Delegate method)
        {
            ThreadPool.QueueUserWorkItem(delegate
            {
                m_activity.RunOnUiThread(delegate
                {
                    method.DynamicInvoke(null);
                });
            });
        }

        public void Invoke(Delegate method, object[] @params)
        {
            m_activity.RunOnUiThread(delegate
            {
                method.DynamicInvoke(@params);
            });
        }

        public void BeginInvoke(Delegate method, object[] @params)
        {
            ThreadPool.QueueUserWorkItem(delegate
            {
                m_activity.RunOnUiThread(delegate
                {
                    method.DynamicInvoke(@params);
                });
            });
        }
    }



> -----Original Message-----
> From: monodroid-boun...@lists.ximian.com [mailto:monodroid-
> boun...@lists.ximian.com] On Behalf Of Chris Tacke
> Sent: Monday, February 20, 2012 10:18 AM
> To: Discussions related to Mono for Android
> Subject: [mono-android] Analog for Control.[Begin]Invoke
> 
> I'm porting the OpenNETCF IoC framework to Mono for Android.  The code
> was almost compatible as-is, but there's one part that needs some
> Android-specific implementation.
> 
> The framework provides event aggregation, and one of the options for
> event subscribers is the context in which to run - either in the
> caller's context or the UI context.  For the full and compact
> frameworks I simply used Control.Invoke (or BeginInvoke).  Obviously
> that's not going to work in Mono for Android.  What I'm looking for is
> the "best" way to achieve the thread migration.  The code where this
> runs has no direct reference to any type of container object (Activity,
> etc).
> 
> I've played with the idea of using an AsyncTask, but it didn't seem to
> behave the way I expected (though my understanding of the class could
> easily be wrong).  I then wondered if maybe I should just create an
> Activity and use 'RunOnUiThread' instead.
> 
> Basically what I'm trying to create is a generic "invoker" class that
> exposes Invoke and BeginInvoke and I'm looking for some sort of
> direction on what's going to be a reasonable mechanism to implement
> this.
> 
> Here's my (failed) first attempt.
> 
>     public class UIInvoker
>     {
>         public void Invoke(Delegate method)
>         {
>             new UITask(false, method).Execute();
>         }
> 
>         public void BeginInvoke(Delegate method)
>         {
>             new UITask(true, method).Execute();
>         }
> 
>         public void Invoke(Delegate method, object[] @params)
>         {
>             new UITask(false, method, @params).Execute();
>         }
> 
>         public void BeginInvoke(Delegate method, object[] @params)
>         {
>             new UITask(true, method, @params).Execute();
>         }
> 
> 
>         private class UITask : Android.OS.AsyncTask
>         {
>             Delegate m_method;
>             object[] m_params;
>             bool m_async;
> 
>             public UITask(bool async, Delegate method)
>                 : this(async, method, null)
>             {
>             }
> 
>             public UITask(bool async, Delegate method, object[]
> @params)
>             {
>                 m_async = async;
>                 m_method = method;
>                 m_params = @params;
>             }
> 
>             protected override void OnPreExecute()
>             {
>                 if (!m_async)
>                 {
>                     m_method.DynamicInvoke(m_params);
>                 }
>             }
> 
>             protected override Java.Lang.Object DoInBackground(params
> Java.Lang.Object[] @params)
>             {
>                 return null;
>             }
> 
>             protected override void OnPostExecute(Java.Lang.Object
> result)
>             {
>                 if (m_async)
>                 {
>                     m_method.DynamicInvoke(m_params);
>                 }
>             }
>         }
>     }
> 
> When I run a quick test like this:
> 
>             new Thread(delegate
>                 {
>                     Thread.Sleep(1000);
>                     System.Diagnostics.Debug.WriteLine("Before
> invoke");
>                     m_invoker.Invoke(new EventHandler(Invokee), new
> object[] { this,  EventArgs.Empty });
>                     Thread.Sleep(1000);
>                     System.Diagnostics.Debug.WriteLine("After invoke");
>                 })
>                 .Run();
> 
>             Thread.Sleep(5000);
> 
> ...
> 
>         private void Invokee(object sender, EventArgs a)
>         {
>             System.Diagnostics.Debug.WriteLine("invokee");
>         }
> 
> I would expect the "invoke" to run last, after the UI thread unblocks,
> but that's not the behavior I'm seeing.
> 
> 
> -----------------
> Chris Tacke
> President
> OpenNETCF Consulting, LLC
> 
> 
> 
> _______________________________________________
> Monodroid mailing list
> Monodroid@lists.ximian.com
> 
> UNSUBSCRIBE INFORMATION:
> http://lists.ximian.com/mailman/listinfo/monodroid
_______________________________________________
Monodroid mailing list
Monodroid@lists.ximian.com

UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid

Reply via email to