Friday, March 23, 2007

SDF 2.1 Preview - Get LIT

Ever have a business scenario where you want your application to perform some task on a periodic basis but the period will be very long - maybe days, weeks or even months?  You want it to occur if the device is asleep or aware at the time?  Well we've got a new SDF class that's designed for this: the LargeIntervalTimer (or LIT).

Let's look at a simple scenario.  Let's say I'm writing a custom calendar.  I want to set up a recurring meeting.  Well let's say the first meeting will be tomorrow at the same time as it is now (for simplicity) and then every 7 days after that.  We want the device to do something on that period (presumably make a noise, vibrate or whatever. 

The LIT is specially designed for this type of scenario.  The code to do achieve that scenario would look like this:

// we want the first timer event o happen 1 day from now
m_lit.FirstEventTime = DateTime.Now.AddDays(1);

// after the first event, we want it to fire every 7 days
m_lit.Interval = new TimeSpan(7, 0, 0, 0);

// we want it to be recurring
m_lit.OneShot = false;

// wire up a handler
m_lit.Tick += new EventHandler(LIT_Tick);

// start the timer
m_lit.Enabled = true;

That's it.  No P/Invokes.  No ugly Notifications, threads, events or whatever.  We've swept all that ugliness under the rug for you so all you need to do it implement your app.

3/23/2007 4:56:43 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [1]  | 
 Thursday, March 08, 2007

And so ends the debate of whether you can time an engine by ear or not.

 

3/8/2007 9:00:38 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Thursday, March 01, 2007

I've been writing apps in mostly C# for several years now.  Of course I've also been doing drivers and kernel work in C or C++, and that has only improved my ability to write, debug and understand managed code in ways that pure managed developers will never really get.  Hell, I pretty much believe that if your managed code doesn't require allowing unsafe code then it could probably be done better.

Well for a few months now I've been neck-deep in a C++ application.  It was started using MFC, which tends to give me a rash just by saying the letters, but it was a customer decision not mine.  At any rate, I was doing some work with a RAS class where I needed any number of consumers to be able to be notified of any changes in the RAS dial status (dialing, connecting, authenticating, etc.).

Imagine a C# class for RAS that will expose events for when the dial staus changes.  THe first thing you'd need is a delegate, right?

In C# you'd have this (assuming DialStatus is an enum):

delegate void DialStatusChange(DialStatus dialStatus);

Well the c++ I wrote (without even thinking about C#) looked eerily familiar:

typedef void(*DIAL_STATUS_DELEGATE)(DialStatus newStatus);

In C# you'd use the += or -= operators for adding an event handler to a classes event, so we get spoiled.  In VB, you call AddHandler with the event name and then the address of the handler.  Well my C++ had a private vector of function pointers (which the CF maintains internally):

std::vector <DIAL_STATUS_DELEGATE> ConnectionManager::m_statusCallbackList;

And then I added methods for adding and removing handlers to the class:

 void ConnectionManager::StatusAddHandler(DIAL_STATUS_DELEGATE callback)
 {
   m_statusCallbackList.push_back(callback);
 }
 
 void ConnectionManager::StatusRemoveHandler(DIAL_STATUS_DELEGATE callback)
 {
   std::vector<DIAL_STATUS_DELEGATE>::iterator iterator;
 
   for(iterator = m_statusCallbackList.begin() ; iterator != m_statusCallbackList.end() ; iterator++)
   {
     if((*iterator) == callback)
     {
        m_statusCallbackList.erase(iterator);
        break;
     }
   }
 }

And how about usage?  In C#, our event-exposing class would have a defined event:

 event DialStatusChange OnStatusChange;

and then when we want to raise the event (assume it's multicast) from our app, we'd do something like this:

 if (OnStatusChange != null)
 {
     foreach (DialStatusChange dsc in OnStatusChange.GetInvocationList())
     {
         dsc(newStatus);
     }
 }

Well my C++ didn't need the event declaration, but raising the "event" (which is simply calling a function pointer callback) looked like this:

 std::vector<DIAL_STATUS_DELEGATE>::iterator iterator;
 
 recheck2:
 for(iterator = m_statusCallbackList.begin() ; iterator != m_statusCallbackList.end() ; iterator++)
 {
   if(IsBadCodePtr((FARPROC)(*iterator)))
   {
      // invalid callback found (someone hooked us then died without unhooking)
      m_statusCallbackList.erase(iterator);
      goto recheck2;
   }
      (*iterator)(status);
 }

Now this was just off the top of my head, so maybe there are improvements that could be made, but it kind of surprised me how I'd taken the concepts I really learned in C# and translated them back to my C++ code.  So yes, writing C# can make you a better C++ developer.

3/1/2007 12:02:32 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Thursday, February 22, 2007

For all those naysayers who complain that we don't do enough free stuff for the community, here's another contribution:

We're now hosting the latest zlib source for Windows CE and a managed wrapper for it.  Click the bitmap or here for more info.

2/22/2007 11:49:30 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  | 
 Tuesday, February 13, 2007

Now this is a great way to pay your bills.

 

What now indeed.  For you non-math people, the value is roughly $1.002. If you're interested in the story behind it (and the audio really is worth listening to) you can find it here.

2/13/2007 12:10:09 PM (Eastern Standard Time, UTC-05:00)  #    Comments [2]  | 

After what seems like forever, the .NET Micro Framework is finally outDownload it here. Expect announcements over the next days from hardware vendors with development platforms.

2/13/2007 9:13:52 AM (Eastern Standard Time, UTC-05:00)  #    Comments [1]  |