Easier Winform UI Thread Safe Methods with DynamicProxy2 and Osherove.SimpleInterception

My blog has moved. You can view this post at the following address: http://www.osherove.com/blog/2007/5/19/easier-winform-ui-thread-safe-methods-with-dynamicproxy2-and.html
Published Saturday, May 19, 2007 4:16 AM by RoyOsherove
Filed under: , , ,

Comments

Saturday, May 19, 2007 11:16 AM by Wendy

# re: Easier Winform UI Thread Safe Methods with DynamicProxy2 and Osherove.SimpleInterception

During the past couple of days? You mean at some point between Ayende's talk and staying up until 4am and doing something like traveling on Friday... well I guess thats a couple of days :) I really enjoyed this part of Ayende's talk and love where you took it. Very sweet!
Saturday, May 19, 2007 3:01 PM by jayson knight

# re: Easier Winform UI Thread Safe Methods with DynamicProxy2 and Osherove.SimpleInterception

Interesting you should post this as I've been scratching my head thinking there must be an easier way than:

if (this.InvokeRequired)

this.Invoke(new MethodInvoker(delegate()

{

  doSomeUIWork();

}));

else

{

  doSomeUIWork();

}

for every single UI updating method in a form.

Have you done any performance benchmarks?

Saturday, May 19, 2007 4:10 PM by RoyOsherove

# re: Easier Winform UI Thread Safe Methods with DynamicProxy2 and Osherove.SimpleInterception

Jason: No Benchmarks, but then, when you're updating your UI from a background thread, that's hardly a perf-issue.

I am doing some caching on the proxy side of things to make sure that I don't re-get all attributes of a method on every call to it, but only on the first call.

basically that means that the "GetCustomAttributes() method is called once per virtual method on a form, which should definitely save some cycles.

It also ignores the "WndProc" loop totally.

I have not used this yet on a real application, but after a bit of smoke testing it seems to be ok (that is - no smoke is coming out of my machine when I test it!)

Roy.

Saturday, May 19, 2007 9:24 PM by Chris

# re: Easier Winform UI Thread Safe Methods with DynamicProxy2 and Osherove.SimpleInterception

That's a good idea - but maybe more flexible to refactor to a method that accepts a delegate (by which you can supply an anonymous one)? Chris
Sunday, May 20, 2007 2:02 PM by hammett

# re: Easier Winform UI Thread Safe Methods with DynamicProxy2 and Osherove.SimpleInterception

I _think_ we have a facility that do that (not sure if Ayende mentioned it). Craig Neuwirt has developed it. http://svn.castleproject.org:8080/svn/castle/trunk/Facilities/Synchronize/
Sunday, May 20, 2007 3:17 PM by RoyOsherove

# re: Easier Winform UI Thread Safe Methods with DynamicProxy2 and Osherove.SimpleInterception

hammet: no, he didn't mention it.

Looking at the code, it certainly looks like it will do the job!

Cool.

I still prefer using my way because it allows very easy out of the ox extensiblity with intercepting attributes with just one single class.

Thanks for the update!

Friday, July 20, 2007 1:29 PM by Paul

# re: Easier Winform UI Thread Safe Methods with DynamicProxy2 and Osherove.SimpleInterception

Can't test this thing in NUnit because it hangs on the Invoke call.. But works when launched as a normal winform. Tried not using forms at all at first and just instantiating a button and checking invokerequired from another thread but it always returned false. Any ideas why?

       [Test]

       public void TestNormalFormCrossThreadedProblem() //this simulates what happens on a winform app when functionality is called in a different thread

       {

           TestSetup();

           //create and launch form which is set to do a cross threaded operation for testing our AOP method of easily getting around the cross threaded UI issue

           AOP_TestForm form = new AOP_TestForm(AOP_TestForm.LoadTypeEnum.Bad);

           form.InvokeRequiredEvent += new AOP_TestForm.InvokeRequiredEventType(form_InvokeRequiredEvent);

           form.Show();

           InvokeRequiredWait.WaitOne();

           form.Dispose();

           Assert.IsTrue(InvokeRequired);

       }

       [Test]

       [Ignore]

       //this hangs for some reason in a unit test but if you uncomment the program class in the test form, change the project type to winform and launch you can see it work properly

       //not sure why, but for some reason the Invoke whether called through AOP or not hangs when done through the unit test

       public void TestFormCrossThreadedProblemFixAOP() //this simulates what happens on a winform app when functionality is called in a different thread

       {

           TestSetup();

           //create and launch form which is set to do a cross threaded operation for testing our AOP method of easily getting around the cross threaded UI issue

           AOP_TestForm form = Maverick.Shared.AOP.AOPFactory.Create<AOP_TestForm>();

           form.InvokeRequiredEvent += new AOP_TestForm.InvokeRequiredEventType(form_InvokeRequiredEvent);

           form.Show();

           InvokeRequiredWait.WaitOne();

           form.Dispose();

           Assert.IsFalse(InvokeRequired);

       }

Friday, August 03, 2007 10:43 AM by Israel A

# RunInUIThread

Friday, August 03, 2007 2:53 PM by Paulo Morgado

# re: Easier Winform UI Thread Safe Methods with DynamicProxy2 and Osherove.SimpleInterception

A few years ago I built a framework in .NET 1.1 to be used by former web programmers (with no previous knoledge of threading or Windows Forms) that had a class Event with a Fire method that took the delegate to fire and, if not null, iterated though the invocation list (Delegate.GetInvocationList()) and, if the Delegate.Target was of a type implementing System.ComponentModel.ISynchronizeInvoke Interface, it would call Traget.Invoke; otherwise Delegate.DynamicInvoke was used.

Couldn't the same be used here?

Wednesday, March 26, 2008 12:47 PM by Jacob Lewallen

# Announcing MultiFunctionMachineMachine

I&#39;m very pleased to formally announce a project that Aaron and I started a few months ago and have

Sunday, June 14, 2009 4:28 PM by Using Castle.Facilities.Synchronize - QEF

# Using Castle.Facilities.Synchronize - QEF

Pingback from  Using Castle.Facilities.Synchronize - QEF