[mono-android] Analog for Control.[Begin]Invoke
Chris Tacke
ctacke at opennetcf.com
Mon Feb 20 16:50:41 UTC 2012
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-bounces at lists.ximian.com [mailto:monodroid-
> bounces at 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 at lists.ximian.com
>
> UNSUBSCRIBE INFORMATION:
> http://lists.ximian.com/mailman/listinfo/monodroid
More information about the Monodroid
mailing list