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

Reply via email to