Jeffrey Richter's Blog, page 2
May 25, 2011
My CLR via C#, 3rd Edition book is E-Book deal of the day on May 26, 2011
Just $23.99. Save 50% w/code DDCV3 http://oreil.ly/musvJw
[image error]May 11, 2011
Wintellect Azure Contest for XBOX 360 Kinect Bundle
Wintellect is conducting a contest where you could win an XBOX 360 Kinect Bundle. THis contest requires minimal effort from you. To register, all you have to do is signup up for a free Windows Azure pass and deploy a service that is provided for you. You do not need to install anything on your computer to participate. For instructions and to see your chances of winning (updated in real-time), go to http://WintellectAzureContest.cloudapp.net/.
As I write this blog post, only 1 person has registered so far so your odds of winning are VERY good!
[image error]April 27, 2011
Microsoft and Wintellect Present - Azure Deep Dive with Jeffrey Richter
I am doing a FREE full-day seminar on programming for Windows Azure in 4 cities in mid-May 2011. The New York event will be broadcast live over the internet. To register for an in-person event, please see https://www.wintellect.com/Training/Webinar/Registration. To register for the live streaming event, please see https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032484438&EventCategory=4&culture=en-US&CountryCode=US.
April 4, 2011
Windows Azure Deep Dive with Jeffrey Richter: Explore the Benefits of Windows Azure Data Storage and Compute Services
Wintellect is working with Microsoft to offer a free 1-day Windows Azure event hosted by me. You can find more information at https://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032484438&EventCategory=4&culture=en-US&CountryCode=US
April 1, 2011
March 17, 2011
Weak Event Handlers
In a few editions of my book, I showed how to implement weak event handlers which allow an object to be GCd if no other reference is keeping the object alive. If the object is alive, it recieves the event notification and if it isn't alive, it doesn't receive the event notification. It has come to my attention that the code I show in my book is incorrect and does not work as advertised. I have corrected that code and the working version is shown below:
public static class WeakEventHandler {
private class WeakEventHandlerImpl {
protected readonly WeakReference m_wrTarget; // WeakReference to original delegate's target object
protected Delegate m_openEventHandler; // "Open" delegate to invoke original target's delegate method
public WeakEventHandlerImpl(Delegate d) { m_wrTarget = new WeakReference(d.Target); }
// Match is used to compare a WeakEventHandlerImpl object with an actual delegate.
// Typically used to remove a WeakEventHandlerImpl from an event collection.
public Boolean Match(Delegate strongEventHandler) {
// Returns true if original target & method match the WeakEventHandlerImpl's Target & method
return (m_wrTarget.Target == strongEventHandler.Target) && (m_openEventHandler.Method == strongEventHandler.Method);
}
}
// "Open" delegate definition to quickly invoke original delegate's callback
private delegate void OpenEventHandler<TTarget, TEventArgs>(TTarget target, Object sender, TEventArgs eventArgs)
where TTarget : class
where TEventArgs : EventArgs;
// A proxy object that knows how to invoke a callback on an object if it hasn't been GC'd
private sealed class WeakEventHandlerImpl<TEventHandler> : WeakEventHandlerImpl where TEventHandler : class {
// Refers to a method that removes a delegate to this proxy object once we know the original target has been GC'd
private readonly Action<TEventHandler> m_cleanup;
// This is the delegate passed to m_cleanup that needs to be removed from an event
private readonly TEventHandler m_proxyHandler;
public static TEventHandler Create(TEventHandler eh, Action<TEventHandler> cleanup) {
Contract.Requires(eh != null && cleanup != null);
// We don't create weak events for static methods since types don't get GC'd
Delegate d = (Delegate)(Object)eh; // We know that all event handlers are derived from Delegate
if (d.Target == null) return eh;
var weh = new WeakEventHandlerImpl<TEventHandler>(d, cleanup);
return weh.m_proxyHandler; // Return the delegate to add to the event
}
private WeakEventHandlerImpl(Delegate d, Action<TEventHandler> cleanup) : base(d) {
m_cleanup = cleanup;
Type targetType = d.Target.GetType();
Type eventHandlerType = typeof(TEventHandler);
Type eventArgsType = eventHandlerType.IsGenericType
? eventHandlerType.GetGenericArguments()[0]
: eventHandlerType.GetMethod("Invoke").GetParameters()[1].ParameterType;
// Create a delegate to the ProxyInvoke method; this delegate is registered with the event
var miProxy = typeof(WeakEventHandlerImpl<TEventHandler>)
.GetMethod("ProxyInvoke", BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(targetType, eventArgsType);
m_proxyHandler = (TEventHandler)(Object)Delegate.CreateDelegate(eventHandlerType, this, miProxy);
// Create an "open" delegate to the original delegate's method; ProxyInvoke calls this
Type openEventHandlerType = typeof(OpenEventHandler<,>).MakeGenericType(d.Target.GetType(), eventArgsType);
m_openEventHandler = Delegate.CreateDelegate(openEventHandlerType, null, d.Method);
}
private void ProxyInvoke<TTarget, TEventArgs>(Object sender, TEventArgs e)
where TTarget : class
where TEventArgs : EventArgs {
// If the original target object still exists, call it; else call m_cleanup to unregister our delegate with the event
TTarget target = (TTarget)m_wrTarget.Target;
if (target != null)
((OpenEventHandler<TTarget, TEventArgs>)m_openEventHandler)(target, sender, e);
else m_cleanup(m_proxyHandler);
}
}
// We offer this overload because it is so common
public static EventHandler Wrap(EventHandler eh, Action<EventHandler> cleanup) {
return WeakEventHandlerImpl<EventHandler>.Create(eh, cleanup);
}
public static TEventHandler Wrap<TEventHandler>(TEventHandler eh, Action<TEventHandler> cleanup) where TEventHandler : class {
return WeakEventHandlerImpl<TEventHandler>.Create(eh, cleanup);
}
public static EventHandler<TEventArgs> Wrap<TEventArgs>(EventHandler<TEventArgs> eh, Action<EventHandler<TEventArgs>> cleanup) where TEventArgs : EventArgs {
return WeakEventHandlerImpl<EventHandler<TEventArgs>>.Create(eh, cleanup);
}
public static Boolean Match(Delegate weakEventHandler, Delegate strongEventHandler) {
return ((WeakEventHandlerImpl) weakEventHandler.Target).Match(strongEventHandler);
}
}
To use it, instead of registerring an event callback like this:
someButton.Click += o.ClickHandler;
Do this:
someButton.Click += WeakEventHandler.Wrap(o.ClickHandler, eh => someButton.Click -= eh);
February 17, 2011
Jeffrey Richter, Wintellect, and Windows Azure
I love computing technologies. I've been programming since 1975 and experimenting with various languages (Basic, Pascal, COBOL, FORTRAN, RPG, APL, C, C++, C#, a little Python) and platforms (mostly DOS, Windows, .NET Framework and Android). During these years, I've consulted, published books, published magazine articles, and produced classes to help others work with these some of the more popular of these technologies. To this day, I've kept up with many of these technologies and I will certainly continue to do so. For example, I expect that I will update my CLR via C# book to cover the next version of the CLR and C# (release date unknown).
However, my nature is such that I'm always looking for the next thing to embrace. After much deliberation, I decided to focus on Windows Azure. And, as such, I along with Paul Mehner (another Wintellectual who has been working with Azure even longer than I) have been working together with it almost daily since August 2010. In addition, I've had numerous meetings and e-mail exchanges with Microsoft Azure team members. And now, I'm finally ready to make some announcements:
And, before anyone asks: At this time, I do not plan on writing a book about Windows Azure development due to the time commitment involved in producing a brand new book. But, hopefully, I can get relevant information out to you sooner (and more cheaply) via all the avenues mentioned above. Also stay-tuned as I will be announcing the release of our new online (premium) content, you must sign up with Wintellect (please note that signing up is free). I will release more details in the coming weeks, so stay tuned.
September 27, 2010
Logical Call Context: Flowing Data across Threads, AppDomains, and Processes
Many developers are familiar with Thread Local Storage (TLS) as a mechanism allowing you to associate a piece of data with a thread. I usually discourage people from using TLS because I recommend architecting applications to perform their operations using thread pool threads. TLS doesn't work with the thread pool because different thread pool threads all take part in a since workflow or operation sequence. However, sometimes people would like to associate some data with a workflow that...
September 22, 2010
Integrating your Application's Threading Model with the Asynchronous Programming Model
In version 2.0 of the .NET Framework, Microsoft introduced the System.Threading. SynchronizationContext class. Simply stated, a SynchronizationContext-derived object connects an application model to its threading model. The FCL defines several classes derived from SynchronizationContext, but usually you will not deal directly with these classes; in fact, many of them are not publicly exposed or documented. Here is what the SynchronizationContext class looks like (I show only the members...
September 1, 2010
Using AppDomains to make Non-Threadsafe code Threadsafe
Recently, I was involved in a Wintellect consulting engagement where a customer had some class library code that was created years ago. The code in this class library was not designed to work well in a multithreaded environment. Specifically, this means that if two or more threads called into the class library code at the same time, the data got corrupted and the results could not be trusted. Non-concurrent-ready code is easy to obtain with frequent use of mutable static fields. But, there...
Jeffrey Richter's Blog
- Jeffrey Richter's profile
- 33 followers
