c pound

I reject your reality and substitute my own!

  Home  |   Contact  |   Syndication    |   Login
  46 Posts | 0 Stories | 25 Comments | 41 Trackbacks

News

Archives

Image Galleries

Blog Communities

Blog is a stupid word

Lunch Hour

Resources

Wednesday, December 20, 2006 #

Asymmetric Accessor Accessibility means you can do this:

public string Name

{

      get { return this.name; }

      protected set { this.name = value; }

}

Is that cool, or what! There a few caveats, so be sure to read the Language Spec page on this topic.

 


Thursday, August 31, 2006 #

I can feel it. I was running the other day, The Distance playing in my ear-buds, and I caught a whiff of it. The scent of rain and plants and cold pavement and other things I can’t remember, a barbeque, maybe. The sun was shining, the clouds were awesome. I had clear road in front of me and nothing to do but run. I had to laugh – a bit maniacally, I admit. Then the moment passed and all returned to the way it was. But, oh yes, fall is here.


Wednesday, August 23, 2006 #

Bloody useful, this code. Especially when threads or timers are involved.

 

class Tracer

{

      private Tracer() { }

 

      public static void WriteTracedDebugLine(string message)

      {

            StackTrace stack = new StackTrace();

            string caller = stack.GetFrame(2).GetMethod().Name;

            string callee = stack.GetFrame(1).GetMethod().Name;

 

            if(message != null && message.Length > 0)

                  Debug.WriteLine(message, caller + " -> " + callee);

            else

                  Debug.WriteLine(caller + " -> " + callee);

      }

}


Monday, August 21, 2006 #

Anonymous methods are a great new feature in .Net 2. Another great new feature is the ParameterizedThreadStart delegate. Since the ParameterizedThreadStart delegate is just a delegate, these two concepts can be combined to effectively create an asynchronous anonymous method – an anonymous thread, if you will. You can spin off a chunk of code to run asynchronously without having to put it into a separate function. Check out the following code:

 

private void AddAsync(int a, int b)

{

      //Define the code we want to run asynchronously.

      // Note that an anonymous delegate works just

      // as well as a ParameterizedThreadStart

      Thread t = new Thread(delegate(object paramArray)

      {

            //get the data we passed into the thread

            object[] param = paramArray as object[];

 

            //do your long-running process here (this part runs asynchronously)

            Thread.Sleep(1000);

            int result = (int)param[0] + (int)param[1];

 

            //when we're done with our asynchronous processing, hit the callback function

            this.Invoke(new AdditionDoneDelegate(AdditionDone), new object[] { result });

      });

 

      //start running the asynchronous code

      t.Start(new object[] { a, b });

}

 

private delegate void AdditionDoneDelegate(int result);

private void AdditionDone(int result)

{

      //this gets called when your asynchronous processing is done

      MessageBox.Show(result.ToString());

}

 

Another cool application for this is to create a partially asynchronous function. You can enclose a long running data access operation, for example, within an anonymous thread and use a non-blocking wait (a mutex) to keep the rest of the function from running until the operation is complete. That’s right, you can make just part of your function run asynchronously:

 

private void AddPartiallyAsync(int a, int b)

{

      int result = 0;

      Mutex mutex = new Mutex();

 

      Thread t = new Thread(delegate()

      {

            //do your long-running process here (this part runs asynchronously)

            Thread.Sleep(1000);

            result = a + b;

 

            //when we're done with our asynchronous processing, release the mutex

            mutex.ReleaseMutex();

      });

 

      //start running the asynchronous code

      t.Start(new object[] { a, b });

 

      //non-blocking-wait here until the thread is done

      mutex.WaitOne();

 

      //continue the function here...

      MessageBox.Show(result.ToString());

}

 

Notice that the code inside the anonymous asynchronous method can access variables defined in the surrounding function. I fully expected there to be scoping that would prevent this. But, amazingly, it works. However, I wouldn’t be surprised if this behavior was eliminated in a later version of the framework. Another surprising part of all this is how well the debugger handles it. Simply amazing!


Monday, March 27, 2006 #

Previously, the discovery of what SQL servers exist on your network was quite a task. The general approach involved PInvoke. Yeah. Now, it .Net 2, it's a one-liner. Sweet!

public List<SQLServer> GetServers()
{
    DataTable dt = SqlDataSourceEnumerator.Instance.GetDataSources();

    List<SQLServer> servers = new List<SQLServer>();
    foreach(DataRow row in dt.Rows)
    {
        SQLServer svr = new SQLServer();
        svr.Name = row.ItemArray[
0] as string;
        svr.InstanceName = row.ItemArray[
1] as string;
        svr.IsClustered = row.ItemArray[
2] as string;
        svr.Version = row.ItemArray[
3] as string;
        servers.Add(svr);
    }
    return servers;
}

Hmm... I just noticed that they used a singleton with one method instead of just making GetDataSources static. Odd.


Tuesday, March 07, 2006 #

Joel likes to run off on little rants right in the middle of an article about whatever. Usually they're great. Sometimes they are dead on:

“If you enjoy programming computers, count your blessings: you are in a very fortunate minority of people who can make a great living doing work they enjoy. Most people aren't so lucky. The very idea that you can "love your job" is a modern concept. Work is supposed to be something unpleasant you do to get money to do the things you actually like doing, when you're 65 and can finally retire, if you can afford it, and if you're not too old and infirm to do those things, and if those things don't require reliable knees, good eyes, and the ability to walk twenty feet without being out of breath, etc.”


Monday, February 27, 2006 #

The ListView control has a flicker issue. The problem appears to be that the control's Update overload is improperly implemented such that it acts like a Refresh. An Update should cause the control to redraw only its invalid regions whereas a Refresh redraws the control’s entire client area. So if you were to change, say, the background color of one item in the list then only that particular item should need to be repainted. Unfortunately, the ListView control seems to be of a different opinion and wants to repaint its entire surface whenever you mess with a single item… even if the item is not currently being displayed. So, anyways, you can easily suppress the flicker by rolling your own as follows:

class ListViewNF : System.Windows.Forms.ListView
{
    public ListViewNF()
    {
        //Activate double buffering
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

        //Enable the OnNotifyMessage event so we get a chance to filter out 
        // Windows messages before they get to the form's WndProc
        this.SetStyle(ControlStyles.EnableNotifyMessage, true);
    }

    protected override void OnNotifyMessage(Message m)
    {
        //Filter out the WM_ERASEBKGND message
        if(m.Msg != 0x14)
        {
            base.OnNotifyMessage(m);
        }
    }
}


Easy but with a couple little catches. If you need to do this, I recommend reading the help on the various properties of ProcessStartInfo. This code runs a console window that is visible to the user. There is a way to run commands by cmd.exe without actually showing a window... and I'm sure you can figure that out if you're interested enough. This should getcha started.

//set up to show a console window and send input to it
string pathToCmdExe = Environment.GetEnvironmentVariable("COMSPEC");
ProcessStartInfo psi = new ProcessStartInfo(pathToCmdExe);
psi.RedirectStandardInput = true;
psi.UseShellExecute =
false;

//open the console windown
Process console = Process.Start(psi);

//send it a command
console.StandardInput.WriteLine("dir");

//TODO: Send more commands, read the results, etc.

//close the console window
console.Close();


Tuesday, February 14, 2006 #

It’s been too long. I can’t believe it’s been over a month since I did a post here. Well, that’s not actually true. I’ve posted a few random photos from my phone. I’ll probably post a whole lot more of those because it’s such an interesting and fun medium. You don’t have to worry about image quality (it’s guaranteed to be bad) so you’re free to focus on composition. Just catch some interesting light or an unusual angle and Blam! You’ve got a cheap (free), modern, lazy form of impressionism… if you will. Actually most of the photos are awful and only make sense to about three people. But hey it’s fun, easy, and no paint stains. Brilliant! Also, if you’re feeling particularly adventurous (and you don’t mind lugging a scanner around) you can make some really… really… well, just go check out the web site. It’s cool stuff.


Thursday, January 05, 2006 #

Say you want to call a method on a control on your form from a thread... For example, you might want to populate a ListBox with a lot of data or with data from a really slow data source. In these cases you'll probably be using a seperate thread to get the data because it's generally a Bad Idea to block (freeze) your UI while you wait for all the data to come in. Especially if the data is of an indeterminate length. So, one way to get at that ListBox from a seperate thread it is to use Control.Invoke:

private void StartAsynchLoad()
{
    this.lstDatabases.Items.Clear();
    //load the databases asynchronously
    Thread t = new Thread(new ThreadStart(LoadDatabasesThread));
    t.Start();
}

private
void LoadDatabasesThread()
{
    //load the databases into the listbox
    string dataSource = this.txtServer.Text;
    string [] names = DataAccess.Instance.GetDatabases(dataSource);
    foreach(string name in names)
    {
        this.Invoke(new AddItemDelegate(AddItem), new object[]{name});
    }
}

private
delegate void AddItemDelegate(string text);
private void AddItem(string text)
{
    this.lstDatabases.Items.Add(text);
}


So, what if you need to pop up a dialog box that could potentially abort the application before you pop up your main form? There are usually no good reasons to construct objects that you don't intend to use. That would include opening a Form which will immediately be closed. But is the following acceptable? I know it's possible... I'm doing it. But what could go wrong in this situation? This must be bad in some way that I haven't found yet.

[STAThread]
static void Main()
{
    //let the user choose a database before we start the program
    DialogResult dr = frmDatabases.Instance.ShowDialog();

    if
(dr == DialogResult.OK)
        Application.Run(
new frmMain());
}


Tuesday, December 20, 2005 #

So, I don’t really have anything to write about that wouldn’t be a rant about boredom, job satisfaction, ridiculous inefficiency, or one of the other states of the various affairs with which I am associated at this juncture. I wish I could post some cool code samples, but that would imply that I had actually written some interesting code lately… which I haven’t. But never fear, all this lack of momentum has prompted me to take much more of an interest in my side projects, which were all previously on hold. I have two main projects in mind which should be pretty slick. They should also generate some interesting bloging material before long. Stay tuned... cool stuff is to coming soon! 


Tuesday, December 13, 2005 #

doo doooo da doo doo!   http://www.devilducky.com/media/7452/

Monday, December 05, 2005 #

... and I'd probably be heading back today, if only my car wasn't in the shop


[Vista Express web-cam pic from this morning]


So... last week I got a new job, had a great day of snowboarding, finished the book I was reading, and saw a good movie with one of my roommates. What a great way to end the week.