Monday, November 5, 2007

Proper Multi-threading in a WPF Application

With most current-gen computers having at least a dual core processor (and in some cases quad-core or Dual CPU), multi-threading is as important as ever to keep in mind when making an application.

1. Use threads for heavy computations.
This one is a basic concept. If you're on your application's main thread, and you have to perform some calculations that could potentially take a long time, always put them on a seperate thread, and use the dispatcher to send the answers back. If you don't, your application could begin to lag or freeze up until the calculations are done, which is very bad.

Actually, anything that might freeze up your application, stick that in a seperate thread. Keeping everything running smooth is your main priority. If your user thinks the program froze, there's a good chance they'll try to close it.

2. Use the dispatcher to send answers back to your main thread.
In WPF, each control in a window has a dispatcher. This gives you a link to the thread that manages this control, and ensures you full access to the control. However, know that commands you invoke through the dispatcher will not be executed immediately.

Based on the priority an invoke is given, the function to be executed is inserted into a queue to be executed at the proper time. Other threads generated in this queue are things such as rendering updates to the screen, databinding, input handling, and so on. Keep commands in your invoke limited to the commands that NEED to be invoked.

3. Not sure if you need to invoke? CheckAccess
Dispatchers have a hidden function (I have no idea why its hidden, because its useful). The CheckAccess function will tell your thread whether it has access to change a control. This is very useful if you have a function that updates a control, and you're not sure when it'll be called from the main thread or a side thread. Here is an example of only performing an invoke when it is required:

private delegate void VoidDelegate();

if (myTextBox.Dispatcher.CheckAccess())
myTextBox.Text = "Hello there!";
else
{
myTextBox.Dispatcher.BeginInvoke(DispatcherPriority.Render, new VoidDelegate(delegate
{
myTextBox.Text = "Hello there!";
}));
}


The VoidDelegate declaration is something I use often for doing anonymous functions, so this also shows how you can call an invoke anonymously. BeginInvoke will allow your thread to continue past this section without waiting for it to complete, or Invoke will wait until your invoked section completes.

4. Leave enough time for your application to render.
This won't be a problem for most people, but if you're in an application that could theoretically want to render very fast, you need to be aware of how long it takes to render. I suppose profiling tools could do this, but since I don't have any here at work, I've just used the Guess & Test method.

I'm running an ultrasound application, that can generate images anywhere between 5 frames per second up to 150 frames per second. Telling my application to re-render 150 times in a second, while generating these images on the fly, as well as doing databinding across dual monitors, each displaying its own live window with the image, is somewhat absurd.

After finding a small hack online to allow me to quickly write to an Image's buffer, I can use InvalidateVisual to tell the Image to re-render. Up to about 30 frames per second, the picture seems smooth. This means the window is taking approximately 35 milliseconds to render. However, past this, I start to experience some lag in the picture. Past 60, I start to experience lag in the entire application. As I approach 150, many parts of the application stop responding. Since I want smooth images, I limit how fast I process my data to 30fps.

Saturday, September 8, 2007

objectClass, objectCategory and the schema

Okay, I don't know how many of you know this, but at work, we're in a domain evironment. One of the tools I'm working on, is a management tool. The program requires that I read a number of objects from a specific organiational unit (OU) in active directory (AD).



If you don't know much about Active Directory, know this. Active Directory is a database of objects, which can contains a property collection. What's the value of the property collection? A property collection. What makes it worse, some objects have certain properties, others don't. And sometimes, objects of the same type have different properties. Confusing, huh?



Well, to alleviate all the headaches, I decided to write a class which will navigate AD. I wanted to have a collection for each type of object. (Right now I am only concerning myself with User, Computer, and Group.) Each object would provide strongly typed wrappers for common properties. To detect the type of object I found in Active Directory, I used the objectClass property. Unfortunately, I found that this won't work.

The objectClass property is indexed. Which means I can use it in my filter clause and filter based on that. However, I wanted everything. So, I tried to manually inspect the objectClass property, and I found that a Computer has many objectClasses, such as User, Person, Computer, and top. (All objects have top.)

The solution is objectCategory. objectCategory contains the Distinguished Name for the schema object that the object inherits. The schema is a class heirarchy which contains mandatory, and optional fields for each type of object. Every single object in Active Directory inherits one of these classes. The distinguished name for the schema class looks something like this:

"CN=Computer,CN=Schema,CN=Configuration,DC=corp,DC=mydomain,DC=com"

We can't always count on that schema using that format, so we must programatically find the schema object programatically. First, we must obtain a DirectoryContext object, like so:

Domain domain = Domain.GetCurrentDomain();
Forest forest = domain.Forest;
m_DirectoryContext = new DirectoryContext(DirectoryContextType.Forest, forest.Name);


This DirectoryContext object allows us to perform a ton of tasks on the entire Directory. To get the schema object, use the following code:



ActiveDirectorySchemaClass cls = ActiveDirectorySchemaClass.FindByName(m_DirectoryContext, "Computer");
DirectoryEntry de = cls.GetDirectoryEntry();
m_SchemaComputerName = (string)de.Properties["distinguishedname"][0];

Notice in the first line, "Computer". This can be substituted with "User", "Group", etc.

Now, you have the Distinguished Name of the Schema class. Compare that with the objectCategory you found on your object, and you should have a match.

Monday, August 27, 2007

CAS and Strong Names

I'm going to be writing some articles on Code Access Security (CAS). CAS is there to prevent a program from doing more than it should. The program is supposed to demand permission to perform the tasks it needs to do. For instance, if a program needs to access the registry, it should demand rights to do so. If it needs network access, it should demand rights to do so. A freecell game should not need to access the network, so it should not demand those rights. My example program for this will be MyCardGame (A .NET application).

Given these demands, the systems administrator can grant specific rights to those programs. For instance, using a "Deny All, Allow Some" security methodology, a systems administrator will deny all rights for that program, except for the ones it needs. For the example program, MyCardGame, the systems administrator will allow GUI usage, as well as Keyboard/Mouse. (S)he will then deny everything else.

Then when the user runs this program, MyCardGame, the OS will then allow it to do any GUI work it needs to do, as well as any keyboard/mouse work. It will deny everything else. Normal operation, that is just fine.

Now, suppose a malicious hacker changes the code in MyCardGame to do 'evil' tasks, such as reading the registry, the OS will deny it. That's wonderful, exactly as we expected.

Take another sample application, MyManagementApp, which requires registry access. The systems administrator knows that this program needs registry access, so it allows it. All is good, until the malicious hacker changes the code in MyManagementApp, to make it clobber values in the registry. Not good.

So how do we prevent this? The key is, the systems administrator needs to be assured that MyManagementApp is really MyManagementApp, and not some hacked version. Strong names prevent this.

A strong name is a 1024 bit RSA public/private key pair. Once you attach a strong name to an assembly, you cannot change it (without breaking the strong name). If you try changing code, without removing the strong name from the assembly, it will not let you run the app.

Note, that it is still possible to change the code. All you have to do is remove the strong name. So how does this help us? This is exactly what we're trying to prevent. With CAS, we're actually trying to prevent malicious code from doing what its not supposed to do.

When the systems administrator allows MyManagementApp to access the registry, (s)he really is allowing the strong name access to the registry. If the malicious hacker changes the code, (s)he has to remove the strong name. As soon as (s)he does this, it is no longer MyManagementApp, and therefore is not allowed to access the registry. Mission successful.

So how do we attach a strong name to our assembly? It's actually pretty easy. First, create your assembly. Once complete, go to your project settings (Right click on your project, go to Properties). In the "Signing" tab, near the bottom, there is a check box called "Sign the Assembly". Select this. Then, from the drop down box, choose "". Type in a key name, with .snk extension (I prefer strongname.snk), and optionally, a password. Press OK. Rebuild your project.

That's it. Your assembly now has a strong name, and it will continue to do so. Since you maintain control of the private key, no one else can make assemblies with this strong name. Your end-users now have a guarentee that if a project has your strong name, then it is, without a doubt, the program you say it is. They can elevate with confidence.

Sunday, August 26, 2007

Friends don't let friends program as administrator

It's been a while since I wrote anything, but I came across a little gem. Michael Stiefel wrote an article about Code Access Security, or CAS. At the end of the article, he states "Friends don't let friends program as administrator." Why is that, you may ask? Well, here is a scenario. I work with a network containing thousands of users. They're all managed with a domain. Now, of course, we don't want to give administrative rights to every single user. We limit the administrators to 1-5 per unit. These administrators have two accounts. They have a user account (for using the internet) and an administrative account. For security reasons, the administrative account is blocked from all HTTP, FTP, etc.

Over the months that I've been here, I've become a remote administration buff. I hate getting out of my chair. Previously, when I was back in the states, I was logged in as an account that had administrative access to my entire unit. Now, I am forced to be on a non-administrator account, and use the "Run As..." function to perform tasks. Works all fine and great - until you run into something that you can't use "Run As..." for.

The point is that you cannot guarentee that a user will have the same rights as you do when you create the program. Jeff Atwood, in The Programmer's Bill of Rights, states that all programmers should have a fast PC, for development. However, the comments below state that programmers should not only have a fast PC, but a median PC, something equivalent to what average users would have.

A good programmer wears two hats. The first hat, is the developer. The developer writes the code, makes the magic happen. However, every developer must know their roots. Every developer started off as a user. Developers have a job because of one thing - the user. If a program doesn't have a single user - it doesn't need to exist.

That said, every programmer needs to swap between these two hats. They develop in the developer's hat... Then all testing should be done in the user hat. This ensures that you, as the developer, experience every single issue that the user would experience, including lack of administrative rights.

You cannot assume that a user has any administrative rights. When you do need administrative rights for your program, you should use CAS. CAS will let the administrators know what rights you need.

Friends don't let friends program as administrator.

Wednesday, August 22, 2007

Converting persisted data using XMLSerializer and implicit operators

So, the other day, ascendedguard was telling me about one of his projects. He is reading javascript style timestamps from an XML source, and storing them in his application as a DateTime. He is currently doing the conversions by hand. He asked me to find A better way™.


My method today will focus on implicit operators. Using implicit operators, we can create a drop in class to replace DateTime. This class will provide all the functionality of DateTime, as well as a seamless conversion to javascript style timestamps.


The class uses a UInt64 to hold the javascript style timestamp internally. It then has constructors to create a timestamp class from a UInt64, double, DateTime, or another Timestamp. It then uses those constructors in implicit operators to those data types.


Once complete, this class acts as a bridge between the data types. In your class, you simply change your DateTime classes to a Timestamp class. Your code requires no modifications to keep it working. You can now use this Timestamp as any of the supported data types. However, we want to read the timestamp from the XML file as a UInt64, so we need to create a second property, of type UInt64, which uses the Timestamp object as a field. So, in the end, you may have properties, Timestamp TimeModified, and UInt64 SAVE_TimeModified. Both of these properties would use the private field Timestamp m_TimeModified. Note, that you would need to put [XmlIgnore] on the Timestamp property.


Now, with this method, you have an ugly, unused SAVE_TimeModified property. You can strip that out of your class's public interface by making it internal, however that will break XmlSerializer. The stock XmlSerializer will not serialize internal members, as they are private to the XmlSerializer itself.


So, you have two choices. Use XmlSerializer, and deal with the SAVE_TimeModified, or manually parse the XML, and have SAVE_TimeModified hidden. In the next few days, I'm going to be working on my own custom XmlSerializer (again, a drop in class) which will handle not only internals, but much more.


The code for the class is below:

public class Timestamp
{
private static DateTime EPOCH = new DateTime(1970, 1, 1);
private UInt64 m_Value;

public UInt64 Value
{
get { return m_Value; }
set { m_Value = value; }
}

public Timestamp(UInt64 seconds)
{ Value = seconds; }

public Timestamp(DateTime datetime)
{ Value = (UInt64)datetime.Subtract(EPOCH).TotalSeconds; }

public Timestamp(Timestamp timestamp)
{ Value = timestamp.Value; }

public Timestamp(double seconds)
{ Value = (UInt64)seconds; }

public static implicit operator Timestamp(UInt64 seconds)
{ return new Timestamp(seconds); }

public static implicit operator Timestamp(DateTime datetime)
{ return new Timestamp(datetime); }

public static implicit operator Timestamp(double seconds)
{ return new Timestamp(seconds); }

public static implicit operator UInt64(Timestamp timestamp)
{ return timestamp.Value; }

public static implicit operator DateTime(Timestamp timestamp)
{ return EPOCH.AddSeconds(timestamp); }

public static implicit operator double(Timestamp timestamp)
{ return (double)timestamp.Value; }
}

Friday, August 17, 2007

Code Blog Formatter Update

I've updated the code blog formatter slightly, to allow for turning off the line numbers and region formatting. I'll probably post code from here on out without line numbers, so people can more easily copy-paste code.

Updated links and change-list is available in the original post here.

Monday, August 13, 2007

Easier managing of INotifyPropertyChanged

INotifyPropertyChanged is the core of WPF Data Binding. One thing that always pissed me off about INotifyPropertyChanged is that it would require me to pass the name of the property to PropertyChanged(). Well, in VS 2005, refactoring is made very simple. So simple, that if you change the name of the property, and then use the context menu to apply the changes to the entire project - it's done flawlessly. However, some complex data binding can cause you to call PropertyChanged for one property, when you set a completely different property! In those instances, you might 'lose track' of a property name change... What happens if the property name passed to PropertyChanged doesn't match that of the property itself? Data binding breaks!

The solution I came up with? Well, we need to write a helper function to get the name of the current property. To do this, we need to examine how properties work. If I have the property named 'MyProperty', it gets converted to accessors when I compile. 'public int MyProperty' becomes two methods, 'public int get_MyProperty()' and 'public void set_MyProperty(int value)'.

The System.Diagnostics.StackTrace class can be used to get the name of the calling method. So, what I did, was devise a function, that when called, obtains the name of the calling method, ensures that it is, in fact, a property (by testing for leading get_ or set_).

Now, I verify that it really IS a property (and not a method pretending to be a property by being named get_ or set_) by using Reflection. First, we get the type of the class by using this.GetType(). Then we get the property with the name we found earlier. If that property is equal to null, then it is NOT a property. Once I've verified that this thing really is a property, then I call PropertyChanged with the appropriate property name.

Then I wrap all of this up into a class, with static methods, for easier reusability. Code is below.

Note that when using reflection to verify that it is actually a property, there are some caveats. For instance, if you have two properties with the same name, one static, one instanced, you will raise an exception. Read the MSDN article for more information. If you cannot deal with those caveats, you could simply take out the call to IsProperty

1public class PropertyChanger
2{
3 public static void PropChanged(object callerobject, PropertyChangedEventHandler PropertyChanged)
4 {
5 string propertyname = new StackTrace().GetFrame(1).GetMethod().Name;
6 string accessor = propertyname.Substring(0, 4);
7 propertyname = propertyname.Substring(4);
8 if (((accessor == "set_") (accessor == "get_")) && (propertyname.Length > 0))
9 {
10 if (IsProperty(callerobject, propertyname))
11 PropertyChanged(callerobject, new PropertyChangedEventArgs(propertyname));
12 else
13 throw new Exception(propertyname + " is not a property.");
14 }
15 else
16 throw new Exception("Calling method is not a get or set accessor.");
17 }
18 private static bool IsProperty(object callerobject, string propertyname)
19 {
20 return callerobject.GetType().GetProperty(propertyname) != null;
21 }
22 }
23}


And to use this class, just call like this:

PropertyChanger.PropChanged(this, PropertyChanged);

where PropertyChanged is the name of your PropertyChanged is the name of your PropertyChanged event handler.