Thursday, November 24, 2005

The Kite Runner

I’d like to talk a little bit about something else – a book…

A few days ago I’ve started to read The Kite Runner. I know, it’s a little cliché talking about this book, after all the publicity and success it had since it was first published. Nevertheless, I want to give my own point of view.

I haven’t read it through yet. Actually, I’ve read only about 20%, so most of the book is still ahead of me. Frankly, I wish I will never finish it, and keep reading it endlessly. It’s not suspense that drives me of course, it’s the way I feel during the few minutes I spend every day reading it. When I read, it’s as if I’m a child again. Not only does it make me think like a child, or see the world from a child’s eyes, it really makes me FEEL like I’m a child again. I actually dreamed being a child again last night! I think that that, above all, is the real magic of this book. It really transports you to another world you once knew, not only in imagination, but also in real feeling – body and soul.

Add to that great writing, the description of a very interesting culture you never knew, a very special friendship between two boys and a boy’s craving of attention from his father – and you’ve got an experience you really shouldn’t miss!

That’s it about this really incomparable piece of art. I may follow-up on this in a later post when I’m done reading it (hopefully in a few decades…).

Wednesday, November 23, 2005

Making GUI Thread Programming in C# easier - take 3

In my first post on this subject I referred to John Wood’s SafeInvokeHelper. I’ve been using it a lot lately and grown to love it...

I’ve decided to add to it a few features:

  1. In order to avoid having to know (or test using InvokeRequired) whether Invoke should be used or not, I’ve added a mechanism that checks InvokeRequired. If Invoke is not required, the method is called directly (without Invoke), which dramatically improves performance.
  2. In some cases you may want to call a method that does not belong to a Control object using Invoke. One example is when you want to alter the ListView.Items collection or one of the ListViewItem objects in it. Both the collection and the ListViewItem are not descendent of Control, hence do not support Invoke. However, it is pretty obvious that altering these objects has an impact on the UI and thus must be done through the UI thread (imagine changing a ListViewItem.BackColor property). So I’ve added an overload to SafeInvokeHelper that lets you specify the control on which Invoke should be called and the object of the method we actually want to execute.

For more details about the SafeInvokeHelper, please read John’s post.

Thank you John!

P.S: Note that the current implementation does not support overloaded methods.

using System;

using System.Collections;

using System.Reflection;

using System.Reflection.Emit;

using System.Windows.Forms;

...

public class SafeInvokeHelper

{

private static readonly ModuleBuilder builder;

private static readonly AssemblyBuilder myAsmBuilder;

private static readonly Hashtable methodLookup;

static SafeInvokeHelper()

{

AssemblyName name = new AssemblyName();

name.Name = "temp";

myAsmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);

builder = myAsmBuilder.DefineDynamicModule("TempModule");

methodLookup = new Hashtable();

}

public static object Invoke(Control obj, string methodName, params object[] paramValues)

{

return Invoke(obj, obj, methodName, paramValues);

}

public static int counter = 0;

public static object Invoke(Control control, object obj, string methodName, params object[] paramValues)

{

if (!control.InvokeRequired)

{

if (methodName.StartsWith("set_"))

{

string propertyName = methodName.Substring(4);

return obj.GetType().InvokeMember(propertyName, BindingFlags.Instance BindingFlags.NonPublic

BindingFlags.Public BindingFlags.SetProperty BindingFlags.Static,

null, obj, paramValues);

}

else

{

return obj.GetType().InvokeMember(methodName, BindingFlags.Instance BindingFlags.InvokeMethod

BindingFlags.NonPublic BindingFlags.Public BindingFlags.Static,

null, obj, paramValues);

}

}

else

{

counter++;

Delegate del = null;

string key = obj.GetType().Name + "." + methodName;

if (paramValues != null)

{

foreach (object o in paramValues)

{

key += "." + o.GetType().Name;

}

}

if (methodLookup.Contains(key))

del = (Delegate) methodLookup[key];

else

{

Type[] paramList = new Type[obj.GetType().GetMethod(methodName).GetParameters().Length];

int n = 0;

foreach (ParameterInfo pi in obj.GetType().GetMethod(methodName).GetParameters()) paramList[n++] = pi.ParameterType;

TypeBuilder typeB = builder.DefineType("Del_" + obj.GetType().Name + "_" + methodName, TypeAttributes.Class TypeAttributes.AutoLayout TypeAttributes.Public TypeAttributes.Sealed, typeof (MulticastDelegate), PackingSize.Unspecified);

ConstructorBuilder conB = typeB.DefineConstructor(MethodAttributes.HideBySig MethodAttributes.SpecialName MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] {typeof (object), typeof (IntPtr)});

conB.SetImplementationFlags(MethodImplAttributes.Runtime);

MethodBuilder mb = typeB.DefineMethod("Invoke", MethodAttributes.Public MethodAttributes.Virtual MethodAttributes.HideBySig, obj.GetType().GetMethod(methodName).ReturnType, paramList);

mb.SetImplementationFlags(MethodImplAttributes.Runtime);

Type tp = typeB.CreateType();

MethodInfo mi = obj.GetType().GetMethod(methodName);

del = MulticastDelegate.CreateDelegate(tp, obj, methodName);

methodLookup.Add(key, del);

}

return control.Invoke(del, paramValues);

}

}

}

Monday, November 21, 2005

How to Retrieve the Viewable Area of a Window or Control

I was trying to figure out how to find out whether a control is currently viewable or not (in C#). When I say ‘viewable’, I don’t mean ‘Visible’, which is a known property of the control. I wanted to know whether the control is currently hidden by some other application/form or whether part of it or all of it can be seen. I remembered vaguely that there was some way to do that with the Win32 API, but didn’t remember exactly how. Googling a bit I found out that Conrad Jones wrote a nice piece of code that does just that: http://www.codeguru.com/Csharp/Csharp/cs_misc/article.php/c4237/

 

Thanks man!

Sunday, November 20, 2005

Specialized Queues - A Cyclic Queue

I'ts been a while, but I hope I'll be able to keep a normal pace now (a blog post once every few days).
I've posted a new article on the CodeProject: Specialized Queues - A Cyclic Queue .
The idea is to provide a Queue with a limited buffer size. Once the buffer is full and new items are added, the 'oldest' items in the buffer are being dropped. I am using this article also to give a few tips about writing specialized collections in .NET.
Hope it will be useful...