I have uploaded to my blog (http://traxnet.wordpress.com/2009/12/24/synchronizationcotext-for-cocoamono bjc/) the code of our implementation of a SynchronizationContext for Cocoa/Monobjc. Please feel free to comment the implementation, correct it or improve it too.
If you feel like it is ok, we don't mind if you publish the article or the code directly on the Monobjc page or in whatever place you think could be useful for others. Happy Christmas all, Oscar Blasco Senior Software Developer Video Stream Networks, S.L. Telf. +34 96 5993670 Fax. +34 96 5993673 obla...@vsn.es www.vsn-tv.com <http://www.vsn-tv.com/> ------------------------------------------------ using System; using System.Collections.Generic; using System.Text; using System.Threading; using Monobjc.Cocoa; using Monobjc; namespace vsn.MacOSXComponents.Threading { [ObjectiveCClass] public class SyncObject : NSObject { private SendOrPostCallback m_Callback; private Object m_State; public delegate void DeregisterDelegate(SyncObject sync_object); #if USE_SYNCOBJS_DICTIONARY private DeregisterDelegate m_DeregisterDelegate; #endif public static readonly Class SyncObjectClass = Class.GetClassFromType(typeof(SyncObject)); /// /// Initializes a new instance of the class. /// public SyncObject() { } /// /// Initializes a new instance of the class. /// /// public SyncObject(IntPtr nativePointer) : base(nativePointer) { } public override void Dispose() { // This is here for testing purpouses //Console.Write("Disposing SyncObject"); base.Dispose(); } /// /// initializes the synchronization object with the given call back and object state /// /// callback /// state /// if true, the current thread waits until the operation is performed /// public void Initialize(SendOrPostCallback d, Object state, bool wait, DeregisterDelegate dereg_delegate) { m_Callback = d; m_State = state; #if USE_SYNCOBJS_DICTIONARY m_DeregisterDelegate = dereg_delegate; #endif // Call the NSObject's performSelector method from csharp code PerformSelectorOnMainThreadWithObjectWaitUntilDone(ObjectiveCRuntime.Selecto r("bridgedCallback:"), this, wait); } /// /// This is our callback which is invoked by the main thread's runloop /// [ObjectiveCMessage("bridgedCallback:")] public void BridgedCallback(NSObject param) { // Invoke the true callback m_Callback(m_State); #if USE_SYNCOBJS_DICTIONARY // Un register this object from our cache if (m_DeregisterDelegate != null) m_DeregisterDelegate(this); #endif // This region is unsafe as we are not protected against the GC. Monobjc // has a cached reference to this object so shouldn't be a problem but // could be a problem if the implementation changes. // Consider using a CER // GC.Collect(); // Testing // Mark this object for deletion by an AutoreleasePool this.Autorelease(); } } /// /// Cocoa's SynchronizationContext implementation /// /// Only Post and Send methods are implemented /// public class CocoaRunLoopSynchronizationContext : SynchronizationContext { private Dictionary m_SyncObjectsDictionary; private readonly object m_lock = null; /// /// Default constructor /// public CocoaRunLoopSynchronizationContext() : base() { m_SyncObjectsDictionary = new Dictionary(); m_lock = new object(); } public override void Post(SendOrPostCallback d, Object state) { SyncObject sync = new SyncObject(); #if USE_SYNCOBJS_DICTIONARY lock(m_lock) m_SyncObjectsDictionary.Add(sync.GetHashCode(), sync); #endif sync.Initialize(d, state, false, DeregisterSyncObject); } public override void Send(SendOrPostCallback d, Object state) { SyncObject sync = new SyncObject(); #if USE_SYNCOBJS_DICTIONARY lock (m_lock) m_SyncObjectsDictionary.Add(sync.GetHashCode(), sync); #endif sync.Initialize(d, state, true, DeregisterSyncObject); } /// /// Called by SyncObject to remove itself from the dictionary so that no reference is held /// /// target object to unregister private void DeregisterSyncObject(SyncObject sync_object) { #if USE_SYNCOBJS_DICTIONARY lock (m_lock) m_SyncObjectsDictionary.Remove(sync_object.GetHashCode()); #endif } } }