CultureInfo

Tue, November 30, 2004, 11:45 AM under MobileAndEmbedded
One of the FAQs on the CF newsgroup is regarding changing the Thread.CurrentThread.CurrentCulture. The answer is that it is not supported. Instead, the user must change the language on the device and restart your application for changes to take effect [Not restarting the application is possible by reloading ALL resources but the approach is dirty and is as good as restarting the app anyway, so there is no point going through the hassle to do it - trust me].

If your app is running in kiosk mode (or for whatever other reason you wish that the user changes the language through your UI), it is easy to set a dialog up for the said purpose. Just list the languages in a combobox associating with each comboxitem a LCID; when the user selects the language and confirms their selection, you have to change the system language via the SetUserDefaultLCID API (and restart your app). Some devices support MUI, so in those cases you also have to call the SetUserDefaultUILanguage API (and reset/restart the unit).

To finish the story on language change, on our platform I don't go through the APIs but instead apply the changes via the registry (the API is the way to go, but I am not doing that for our own historical reasons - not relevant here). In case it helps someone, these are the registry entries (shouldn't be too different to others):
-HKLM\nls\DefaultLCID
-HKLM\nls\overrides\LCID
-HKLM\SOFTWARE\Microsoft\International\LCID
-HKLM\MUI\SysLang
-HKCU\MUI\CurLang
As you'd expect, I set the LCID in each one of these DWORD values, flush the registry (RegFlushKey) and perform a soft reset (KernelIOControl\IOCTL_HAL_REBOOT).

After your app restarts you may want to know what the locale is. You may do this through CultureInfo.CurrentCultre (and CultureInfo.CurrentUICultre).

Note that sometimes you just need to perform some formatting based on a locale other than the system-wide one e.g. the French decimal point is comma "," and you may want to parse a string containing doubles that come from a network where dot "." is the decimal point. In those cases you have to use overloads of the framework's methods that can accept a CultureInfo (or any other IFormatProvider object) as a parameter, e.g. Double.Parse or DateTime.Parse

Next we look at resources in satellite assemblies.

QFE 4.2 - CF update

Mon, November 29, 2004, 12:52 PM under MobileAndEmbedded
This just appeared:
http://www.microsoft.com/downloads/details.aspx?familyid=e0e66c77-dee2-4aba-9623-a3bfff434b5c&displaylang=en

CF version number appears to be: 1.0.4292.0

Fixes made (from the readme):
This update addresses the following issues:
a.. Transitions between managed and native code may cause memory leaks on ARM platforms.
b.. A NullReferenceException may occur when a Web Method returns an empty array using the xsi:Nil attribute.
c.. Modifying the SoapClientMessage.ContentType property does not modify the Http requests ContentType header.
d.. Stack corruption may occur on SHx, MIPS and x86 platforms when local variables are created but never used.
e.. Invoking a multicase delegate from a catch handler may cause a MissingMethodException on SHx, MIPS and x86 platforms.
f.. Command line arguments containing double byte characters may get truncated to a single byte.
g.. An ObjectDisposedException may occur when a asynchronous web request is aborted before the response is received.
h.. Invoke on a disposed control may hang the application.
i.. An array containing one or more elements may be sent to the Web Service incorrectly.
j.. An application may hang when invoking a Web Method that uses multiple XmlElementAttributes on a single argument, member or property.
k.. Memory corruption may occur on devices that have the native security model enabled and both .NET CF V1 SP3.
l.. Deadlocks may occur when running under severe resource constraints.
m.. The issue of the Tool Bars loosing their image on Windows Mobile 2003 SE when removed from the form is addressed by this update.
n.. An ObjectDisposedException may occur when the server closes the socket connection.
o.. Setting the Minimum and Maximum properties of a progress bar may crash the application.
p.. An exception may occur when adding an image to an imagelist on an Hx4700 and Hx4705.
q.. Data misalignment may occur on decimal fields in MIPSIV devices.

Blog link of the week 48

Sun, November 28, 2004, 12:15 PM under Links
Giagnocavo cracks code!

Jared Parsons mixes Generics and Singleton. I wonder how many patterns can be rewritten using generics... anyone working on that?

Over at Saurabh Verma's blog there is a pretty picture showing a memory representation of a reference type holding a value type. Hopefully we'll get more pretty pictures of more complex scenarios.

Surprise Delivery

Fri, November 26, 2004, 03:03 AM under Random
Got a nice surprise through the post today:
.NET Compact Framework Programming with VB.NET

As I said on my Amazon review of it (the C# version), I had read the draft but didn't actually own the released version.

Further surprise followed when seeing my name in the acknowledgments (page XXXVII) and even more so with my quote on the very first page (3rd one down)!

Someone said "fame at last", but I already said that when I was first (knowingly) acknowledged in the VB6/VB.NET Design Patterns book :-)

mouse_event

Thu, November 25, 2004, 02:46 AM under MobileAndEmbedded
Assuming you read ToolBarButton BUG and ContextMenu.Show...

Let's look at the real solution. The title gives it away really: PInvoke mouse_event. The API is pretty straightforward, but you must RTFM and in particular the bit where it says "...dx and dy contain normalized absolute coordinates between 0 and 65,535".

The DllImport is very easy (all parameters are Int32) and if you STFNG you'll find this. So here is a short sample for performing mouse clicks from code, using mouse_event. Create a winforms smart device project with a Form, 2 buttons and a MainMenu. The code should be self-explanatory and easily translatable to C#.
		

' Wrapper for mouse_event, performing click action on coordinates given
Public Shared Sub PerformMouseClick(ByVal aX As Int32, ByVal aY As Int32, ByVal aForm As Control)
Dim p As Point = aForm.PointToScreen(New Point(aX, aY))
Dim m1 As Int32 = (65535 \ Screen.PrimaryScreen.Bounds.Width)
Dim m2 As Int32 = (65535 \ Screen.PrimaryScreen.Bounds.Height)
Dim x As Int32 = m1 * p.X
Dim y As Int32 = m2 * p.Y
Win32Api.mouse_event(2 Or &H8000, x, y, 0, 0)
Win32Api.mouse_event(4 Or &H8000, x, y, 0, 0)
End Sub

' Button1 event handler. Simulates button click OR opening a main menu. Same principle applies for ToolBarButton
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
PerformMouseClick(Button2.Left + 1, Button2.Top + 1, Me) 'performs click on other button
'PerformMouseClick(5, 5, Me) 'opens main menu on full screen WinCE app
'PerformMouseClick(Me.Left + 5, Me.Height + 5, Me) 'opens main menu on PPC app
End Sub

Finishing off, here are a few tips for playing with mouse coordinates and the above:
1. Use the static method Control.MousePosition to determine where the mouse pointer is (or where you have sent it). E.g. run a timer and when it ticks update a listview with the coordinates.
2. Even better than 1, but only applicable if you are using Platform Builder, add the cursor to your image [it is under Shell_and_UI -> UI -> Mouse]. Now you can see where you are sending the mouse and where you exactly last tapped :-)
3. When passing the coordinates to mouse_event be sure to use the instance method Control.PointToScreen as in the example given above (otherwise e.g. you'll be aiming for the toolbar and hitting the title bar)

Let me know if it (or anything else on this blog) doesn't work for you.

STFNG

Thu, November 25, 2004, 02:37 AM under MobileAndEmbedded
Regular readers of this blog (but also anybody that has been developing with the CF for more than a week), know that there is a one-stop shop for all your CF answers, and it is of course the CF newsgroup. Anybody hanging out there for more than a month will know that the same questions get asked over and over and over and over again (trust me, there are not enough "overs" in this sentence).

Sometimes I wish I could just ask people to STFNGTM

Search The Freaking NewsGroup

The FAQ is also a good place to start.

ContextMenu.Show

Wed, November 24, 2004, 11:07 AM under MobileAndEmbedded
Here we will look at a solution for the bug reported previously. In a nutshell, we have a situation where we would like a menu to automatically appear, but instead the onus is passed onto our code. The solution is more interesting than the problem, and in fact in this case applies to other problems as well, so without further ado...

The initial (obvious) solution is to manually show a ContextMenu, which is easy given the Show method. This takes two arguments (the control and position) and is easy to call. The approach does indeed solve the problem and can be adequate for some scenarios, but is not without its problems. They all stem from the fact that when putting up a ContextMenu you are blocking: "This method does not return until the menu is dismissed".

Consider for example what happens if you are performing asynchronous operations (e.g. network requests) that are Control.Invoked to the GUI (e.g. populate a listview) and suddenly the user taps the ToolBarButton to get a menu and you use ContextMenu_Show: all those threads/messages are blocked in a queue only to be released (all at once!) when the menu is dismissed - I don't fancy that myself.

As a workaround to the aforementioned condition (and also a standalone requirement for some scenarios), you will want to stop other activities before showing the ContextMenu, and restarting them after it is dismissed. But wait, how do you know that they must be restarted when it is dismissed? The conditions/scenarios are different if it was dismissed due to a menu item being clicked (which as a result may have now navigated the user to different forms, for example) and different if the user tapped somewhere else, hence dismissing the ContextMenu. A solution to the new problem is to use a global flag tracking if a menu item was clicked or if the ContextMenu.Show call returned without a menu being clicked (and based on the state of the flag make the decision). As you can see, it gets messy.

Other differences compared to a plain menu include the following scenario: Form A shows form B; form B shows a ContextMenu; Form A decides (e.g. based on a Forms.Timer event) to close form B. The result is you are now looking at Form A while the ContextMenu from form B is still up! The workaround to this is to place a this.Capture = false in the Closing event of the Form.

Talking about the problems of manually showing ContextMenus, it is worth capturing (for the record) a known issue with showing them from the AfterSelect event of a TreeView. Rather than describe it here, I point you to the ng archives here and here [my posts there also include a workaround].

From my previous four paragraphs I hope you can see that ContextMenu.Show is useful and can solve some simple scenarios, but is definitelly not a one-to-one replacement for the user tapping on the arrow part of a ToolBarButton and having the menu auto-displayed for them (where none of the problems above apply).

Next time we look at a much nicer workaround to the original problem.

ToolBarButton BUG

Tue, November 23, 2004, 07:38 PM under MobileAndEmbedded
This blog entry serves as a description of what I call a bug (others might call it a limitation by design). The post after this will describe the workaround solution.

We are all familiar with the Toolbar and ToolBarButtons, right? There is different behaviour in this area of the OS, depending on the platform. On CE they appear at the top, whereas on PPCs they are at the bottom of the screen (no problem so far, but there is more). ToolBarButtons in .NET have a Style property, which by default is ToolBarButtonStyle.PushButton and hence we get normal buttons that we can click on (which we usually assign an icon to). When setting the Style property to DropDownButton, the ToolBarButton becomes “split” and effectively has two parts: the "icon" part and the "arrow" part, the implication being that you will also assign a ContextMenu to the DropDownMenu property.

So, assuming we've setup a toolbar button as described, what does it look like and what does it behave like on the PPC versus vanilla-CE device? (For the following discussion, if you don't have a device handy and wish to check my observations, you can use the emulators. The CE one with VS.NET 2003 is based on 4.1, the bug is only present on 4.2 - trust me!)

Appearance
- On PPCs, the line separating the arrow and icon parts is always visible. So the user (with their handy stylus) gets a hint that, if they click on the arrow part, something different will happen compared to if they tap on the icon part of the toolbar button.
- On vanilla windows CE 4.1/4.2 devices there is no line separating the two, ever! [point A].

Windows Behaviour (native)
- I could not find a native application running on a PPC that uses ToolBarButtons with an arrow (if you let me know of one I'll update this entry - it is irrelevant to my overall point)
- On WinCE 4.1/4.2 we can launch Windows Explorer. Notice that there is a ToolBarButton with an arrow ("Views" - just like on the desktop). The punch line is that tapping anywhere on that button (arrow part OR icon part) will show a menu; there is no separate click action [point B].

.NET Behaviour (managed)
- A managed app on PPC visually separates the icon part from the arrow part, as we established earlier; behaviourally they are also separate, i.e. tapping on the arrow part shows a menu, whereas tapping on the icon part performs a click action. In code you can trap the click action but not the arrow_tap (it will automatically put a menu up).
- A managed app on CE 4.2 behaves the same! [Hint: It shouldn't] On CE 4.1 the behaviour is correct i.e. different to the PPC (and same as the native Windows Explorer)

Conclusion
This is an area where the CF does not conform to the platform it runs on. My claim is that a CF app should not behave the same on PPC and CE devices in this area.
- The main reason it shouldn't is that, as per point A above, there is no visual distinction between the two areas (either fix the bug of the OS or fix the bug of the CF - preferably the latter).
- The second reason it shouldn't is because typically on non-PPC CE devices there is no stylus or mouse, so asking a user to tap within 9 pixels using their finger is a bit much.
- The third reason it shouldn't is because, as per point B above, even native apps don't treat the button as having two behaviours.
- Finally, why break the correct behaviour of CE 4.1?

Next time we'll explore a workaround.

Blog link of the week 47

Sun, November 21, 2004, 02:30 PM under Links
No links here to some new CTP download or to some language feature getting dotslashed (I know it is the other way round :) although I could have linked to the 3 CLR videos

Earlier in the week I came across a writing that expresses a view which I fundamentally disagree with, but at the same time have to admit that the author is absolutely right! It may be long but I suggest you go read Sriram Krishnan entry (and then decide where you stand).

Soon we will be adding web-serving capability to our CE-based product so this entry was very welcome.

VBUG

Sun, November 21, 2004, 12:30 PM under Events
My introduction to .NET was at the annual VBUG conference in 2000. I have never been back to one (mainly cause I go to TechEds instead) but this year Peter Westwood was there. He has a nice write-up of the final day on his blog so go read it!

Book Review

Thu, November 18, 2004, 04:35 PM under dotNET
Maximizing .NET Performance

.NET Framework Tour from a Performance Perspective - 4stars

There are no other books on .NET Performance so, when this one fell in my hands, it put a smile on my face (sad, I know). When I got to the end, I was not disappointed. Around 250 well-written pages over 15 chapters and, as you'd expect, you can delve into it in random order, making it a good reference book. Even so, I read it cover to cover. The first two chapters lay the ground; the last chapter provides generic advice on troubleshooting and the 12 chapters in-between focus on specific .NET areas: a framework tour from a performance perspective. Naturally, a subject of this nature assumes the reader has some .NET experience and targets the Intermediate/Advanced level.

Don't expect material on GUI (Windows.Forms), Database (ADO.NET) and Web (ASP.NET); rather a discussion on elements that every application is built on (Type design/implementation, Strings/Text/RegEx, Collections, Language Specifics, GC & Object Lifetime, Exceptions, Security, Threading, IO/Serialisation, PInvoke, CLR). I challenge you to find a chapter that does not teach you at least one thing you were unaware of before. We have to sum it up with the great technical phrase: "It is all great stuff".

There are no axioms presented, and readers expecting a "cookbook" will be disappointed. Every claim is backed up with a reference to a testcase and even then, only after we have delved under the covers to see *why* something is slow or *how* a change makes something faster. By taking this approach, the reader should be able to repeat the investigation/tests for newer/other versions of the framework. So, having just mentioned how there is a cross-reference to specific testcases, I have hinted at what is one of the best contributions of this book: A .NET Benchmark Test Harness. This is described in the appendix of the book and the code/binaries can be obtained from the publisher's site.

Now how about something like this for the Compact Framework?

Reading books

Thu, November 18, 2004, 11:17 AM under Random
Reading technical books is something I have always enjoyed, including writing reviews about some of them. The very first book I reviewed was over 5 years ago (Doing Hard Time: Developing Real-Time Systems with UML, Objects, Frameworks and Patterns) and the first .NET book I read was in 2000 (Presenting C#).

My recent focus was on .NET Compact Framework Books. I have read and reviewed all of them (let me know if I've missed any - although it's unlikely I'll be reading a book on the CF 1.0 now that the CF 2.0 Beta is out). If you are writing a CF 2.0 book let me know.

Some of my reviews are over at my Amazon page (.NET, UML, OO and COM being the dominant theme).

More and more magazines make their articles available online (and we already subscribe to quite a few at work), even more informative blogs become available with nice technical content and more Alpha/Beta software is made available earlier and to wider audiences. All of this means that my book intake has gone down (hasn't yours?). It is up to you (as a publisher/author) to change that by sending me prospective .NET books to read/evaluate :-)

Having said all that, I recently finished reading Maximizing .NET Performance (I won it at a competition). The review will also appear as my next blog post.

D.D.G. MOTH (Amazon Associate)

Debug.WriteLine

Wed, November 17, 2004, 09:58 AM under MobileAndEmbedded
One of the first complaints .NET desktop developers have when targeting the CF v1.0 for the first time is "Debug.WriteLine doesn't work".

The fact is that with Smart Device projects the debug output does not come back to Visual Studio; rather it goes to the console on the target device. It is true that Debug/Console WriteLine statements do not appear when debugging on PocketPC devices/emulators, but this is not a CF issue; it is rather due to a lack of console on the PPC platform. Debugging a CF app on the CE emulator or a CE-based device results in the display of a console window on the target with the debug statements. Note that even on a CE device, if you build it without the console (cmd.exe) you will get no debug output (I should know, since I have accidentally run into that scenario when we ported from CE 4.1 to 4.2, but I digress).

So what can you do about it? There are a number of options and I will link to them in this entry, ready for the next time someone asks :-)

Add a console to the target, e.g. this one

Redirect the output to a file, e.g. like this

Send the output back to the dev machine, e.g. like that or that

Of course you could switch away from using System.Diagnostics directly and write your own logging framework. As you'd expect, this has been done before and there are a number of 3rd-party solutions, some of which may be too simple and others too complex for your project's liking. So here are some options:

MSFT offer the Enterprise Instrumentation Framework, but I doubt it supports the CF.

I have met references to log4net a few times, but I don't think it supports the CF it is under the Apache license.

Over at the useful openetcf there is a logging system, but I must admit not having played with it, and I don't know if it works on the desktop

For my own projects (CF and full Fx), I have been using a class I wrote years ago. Features include:
1. Just one file to include in your project. Only one class with static methods.
2. Use of the standard Debug class internally, so the output goes to VS console (desktop) or device's console (CF)
3. CSV formatted output (inserting additional info such as timestamp etc.)
4. Redirection of output to a HyperTerminal on the desktop, when running a debug OS on your CE target
5. Support of 3 severity levels (Info, Warning/Assert and Error). Auto detectable based on project configuration (e.g. DEBUG, TRACE)
6. Further configuration available via TraceSwitch (both platforms) and optionally via config file (desktop only)
7. Writing to a file (on both platforms, path and name computed internally also take into account COM Interop clients)
8. Rolling of the filename, thus preserving debug info between different runs of the application

Feel free to play with it.

If you are interested in the subject of tracing, you will love a new feature in Whidbey: Tracepoints. I was going to write about it, but many others have done so already [1,2,3]

UPDATE:
Visual Studio 2005 (and .NET Compact Framework v2.0) support Debug.WriteLine :-D

CF article on MSDN mag

Tue, November 16, 2004, 09:08 AM under MobileAndEmbedded
The December issue of the MSDN Magazine comes with a nice CF article, go read it:
Optimize Your Pocket PC Development with the .NET Compact Framework

Here is its outline:
-Essential Goodies and Our Test Bench
-Bad, Wicked Dialogs
-Chilling Out the Context Menu
-Designable Custom Controls
-Optimization
-Getting Resourceful
-Load Only What You Need; Chuck What You Don't
-Putting It All Together—the TabControlEx Class
-Adding Toolbar Buttons to TabControlEx
-Conclusion

Try Catch IL

Mon, November 15, 2004, 01:01 PM under dotNET
Almost two years ago I was asking why VB adds extra IL lines in try catch situations compared to C#. I got an unsatisfactory answer. Now, someone that seems to agree with my sentiments blogs about it. Cool!

AssemblyFileVersion on CF

Mon, November 15, 2004, 03:58 AM under MobileAndEmbedded
The Compact Framework does not support the AssemblyFileVersion attribute. Instead, whatever .NET version you give to your assembly (via AssemblyVersion) will also be its Win32 file version. Neil shows you how to give an alternate Win32 file version to your CF assemblies without resorting to command line compile. Go read it and let me know when you are back!

OK, so although I am an advocate of everybody understanding both languages, I have done the VB version for you here. Note that this will only work if you have not chosen to use the Root namespace in your VB project properties (which as I've said before is a bad habit anyway).

Namespace System.Reflection
    <AttributeUsage(AttributeTargets.Assembly, AllowMultiple:=False)> _
    Public Class AssemblyFileVersionAttribute
        Inherits Attribute
 
        Private mVersion As String
        Public ReadOnly Property Version() As String
            Get
                Return mVersion
            End Get
        End Property
        Sub New(ByVal aVersion As String)
            If aVersion Is Nothing Then
                Throw New ArgumentNullException("version")
            End If
            mVersion = aVersion
        End Sub
    End Class
End Namespace


While on the subject of versions, it is worth pointing out that the Product Version of your file can be set with the AssemblyInformationalVersion.

Blog link of the week 46

Sun, November 14, 2004, 03:59 PM under Links
You are wrong if you think I'll link to the new browser launch (ieview is the best thing it has going for it) OR about the new MSFT game (when I get time to play a game I go here) OR about the poor devs at that game company (naturally I sympathise) OR about the flash CV of the Frenchman OR about YA search engine and I am definitely not telling you what file extension I am! [if none of these references make sense to you, stay in and read more blogs:-]

Instead, go read why Thread.Abort is evil (good thing the CF doesn't support it then so I didn't use it here :-)

Smart Device Programming Chat

Thu, November 11, 2004, 12:58 PM under MobileAndEmbedded
Earlier today the Compact Framework chat of the month took place. For those of you that don't know about them, check out the schedule for online chats and search the archive of previous transcripts here. So these are opportunities to ask MSFTies and/or MVPs questions regarding a particular technology (in this case the CF).

Some times we may get interesting news out of them as well but, as always, nothing communicated in a chat is a commitment (more like "this is what we believe now"). Example: In a previous chat, I was told that the TreeView in CF 2.0 will support the NodeMouseClick event
"Q: Will CF 2.0 support TreeView.NodeMouseClick (since AfterSelect does not fire when selecting an already selected tree node)?
A: Yes, the NodeMouseClick event will be available in CF 2.0."

Today I was told it is not in CF 2.0 "for reasons of ROM size". Oh well, still if we all go and vote for it, I will feel better.

Other interesting points from today's chat:

Service Pack 3 for CF 1.0 will be out within a month (good news for me, as my next IQView release depends on a SP3 bug fix)

There will be no deterministic GC in CF 2.0 - it is on the consideration list for v3
Same goes for Code Access Security (not in CF2 but planned for future release).

It was confirmed that COM Interop in CF 2.0 is limited to managed clients activating unmanaged COM types. Unmanaged COM code can call managed code in terms of events/callbacks only.

That's all I recall. For the full story, keep an eye out for when the transcript becomes available.

Don't poll

Thu, November 11, 2004, 08:09 AM under dotNET
Sometimes we write code that uses polling. A brief example of that is some method/routine that runs on a timer (e.g. every 5 seconds), reads new entries from a file/database and performs some operation based on the input - and repeates this cycle until we stop the timer.

Although there are valid scenarios for taking the approach described above, there are others where it is a sub-optimal solution. For example, if you need to know as soon as there is a new entry to process, then there is no point waiting for your timer's tick; conversly, if there are no new items to process then there is no point running the function. A similar (equally not good) alternative is instead of running a timer to make the thread sleep for a while.

So in those case where the 2 aforementioned similar solutions are not the best, what is the correct way? Use a thread! The following code shows you an example of how. Note that I use this technique with the Compact Framework so, for example, we need the extra boolean to tell the thread to kill itself/exit since the CF 1.0 threads are missing many properties that could help (e.g. IsBackground, Abort etc).

        // declarations
        private Thread mSendNextThread;            // worker thread
        private bool mStayAlive;    // for controlling the thread termination
        private Queue mQue;                        // buffer of jobs
        private ManualResetEvent mWaitEvent;// signal the thread to wake up
 
        // Initialisation logic
        public void Start(){
            Console.WriteLine("*********");
            Console.WriteLine("Start");
            mQue = new Queue();
            mWaitEvent = new ManualResetEvent(false);
            mStayAlive = true;
            mSendNextThread = new Thread(new ThreadStart(OnMyOwnThread));
            mSendNextThread.Start();
        }
 
        // Tear down logic
        public void Stop(){
            Console.WriteLine("Stop request");
            lock (mQue.SyncRoot){
                mQue.Clear();
 
                // kill the thread
                mWaitEvent.Reset();
                Thread.Sleep(10);
                mStayAlive = false;
                mWaitEvent.Set();
                Thread.Sleep(10);
                mSendNextThread = null;
            }
            Console.WriteLine("Stopped");
        }
 
        // queue more jobs
        public void MoreInput(object someInput){
            Console.WriteLine("More Input: " + someInput.ToString());
            lock (mQue.SyncRoot){
                mQue.Enqueue(someInput);
            }
 
            mWaitEvent.Set();
        }
 
        // process jobs
        public void OnMyOwnThread(){
            while (mStayAlive){
                if (mWaitEvent.WaitOne()){
 
                    mWaitEvent.Reset();
                    while (mQue.Count > 0){    //Whether we do the looping depends
                                            //on the specifics of DoWork
                        if (!mStayAlive){
                            break;
                        }
 
                        this.DoWork2();
                        mWaitEvent.Reset();
                    }
                }
            }
            Console.WriteLine("Thread exiting");
        }
 
        private void DoWork2(){
            object queObj = null;
            lock (mQue.SyncRoot){
                if (mQue.Count > 0){
                    queObj = mQue.Dequeue();
                }
            }
 
            // do some long processing with this job/input
            if (queObj != null){
                Console.WriteLine("Processing: " + queObj.ToString());
                Thread.Sleep(300);//LONG PROCESSING
                Console.WriteLine("Processed " + Environment.TickCount.ToString());
            }
        }

CopySourceAsHtml

Wed, November 10, 2004, 09:29 PM under Links
Testing if this works in blogger

C# (btw, for the full MsgQueue API set look here)
        /// <summary>
        /// This function opens a handle to an existing message queue based on 
        /// a message queue handle.
        /// </summary>
        /// <param name="hSrcProc">[in] Handle to a source process that owns the 
        /// hMsgQ message queue handle. </param>
        /// <param name="hMsgQ">[in] Handle to a message queue returned by the 
        /// CreateMsgQueue function.</param>
        /// <param name="lpOptions">[in] Pointer to an MSGQUEUEOPTIONS structure 
        /// that sets the properties of the message queue.</param>
        /// <returns>Returns a handle to a message queue, or returns NULL if the 
        /// queue could not be opened.</returns>
        [DllImport("coredll.dll", SetLastError=true)]
        public static extern IntPtr OpenMsgQueue(IntPtr hSrcProc, IntPtr hMsgQ,    
            MsgQueueOptions lpOptions);


VB (btw, this is a another example of this)
    Private Function DoWork2() As Boolean
        ' If I don't have a requester then I can't do anything with the input 
        ' so ignore it (and don't obtain the lock!)
        Dim req As ForMyPending = Nothing
        req = Me.FindFreeRequester
        If req Is Nothing Then
            Return False
        End If
 
        ' Get the next object from the queue
        Dim queObj As ForMyQueue = Nothing
        SyncLock mQue.SyncRoot
            If mQue.Count > 0 Then
                queObj = DirectCast(mQue.Dequeue(), ForMyQueue)
            End If
        End SyncLock
 
        ' Deal with the next object from the queue without holding the lock!
        If Not queObj Is Nothing Then
            If queObj.ReqArgs.MaxNumResponses <> 0 Then'chance for client to cancel
                req.Deleg = queObj.Deleg
                If req.Requester.Request(queObj.ReqArgs, queObj.State) = False Then
                    If Not req.Deleg Is Nothing Then
                        req.Deleg.Invoke(Me, ReplyArgs.Empty)'failed
                        req.Deleg = Nothing'otherwise it wil never be reused again!
                    End If
                End If
            End If
        End If
 
        Return True
    End Function


Nick Cave Looking For a Job

Wed, November 10, 2004, 06:06 PM under Personal
Just came back from a Nick Cave concert. I am not some big fan but Jenny is crazy about his music so she dragged me up to Brixton and now I must thank her for a good night out!

Speaking of my girlfriend, she is looking for a ASP.NET/C# job in Sussex so let me know if you are interested. With 4 years development experience (Java/Delphi) and having just completed an MSc (7 .NET projects), I'd hire her! Here is a public "congratulations" for getting a distinction on your MSc project!

Blog link of the week 45

Sun, November 7, 2004, 02:42 PM under Links
Windows CE 5.0 - Get the Facts, by Mike Hall

While on the subject of CE, a bunch of QFEs for all versions were published this week; if you want to know when MSFT downloads are available just subscribe to their rss feed (e.g. then you'd know that this week a new .NET CF sample became available also)

My.IsNot.For.Me

Thu, November 4, 2004, 03:59 PM under Whidbey | VisualStudio
If you are not familiar with the new My feature of VB2005, please go read about it and make your own mind up. I suggest reading my previous entry (in addition to the two links I offer there also check these out [1,2])

So it is clear that we are talking about:
1. A speed dial into the framework
2. Application events
3. Stuff generated at compile time into your project

My opinion is that the first one is a waste of space. Speed dial?! They could have given us this as example code and be done with it (or invest the energy to improving the help/navigation system). Yes the framework is large and some times discovering some methods may take longer than what it should, but how does having a parallel framework help? Now I have two frameworks to learn! We don't need YAF (yet another framework). The process of discovering the framework is called "becoming a .NET developer". While searching for a solution to a problem, the developer discovers not only the correct namespace/class/method but also a bunch of other classes/methods that they will not have to search for next time they have a different problem. The My feature discourages this behaviour and hence hinders learning the framework (which can only be a bad thing).

I wasn't too thrilled with VB.NET 2002 when I discovered all those "global" functions that come as part of Microsotf.VisualBasic.dll However, there is a major difference with those: they are necessary for smooth upgrade of VB6 code by tools (and some parts of it actually offer functionality not found in the framework). VB2005 takes the VB6 approach of having global functions everywhere and repackages them in a structured library. Structured or not, it is still a bunch of globals that existing .NET devs did not need (globals=statics.. err sorry I meant shared). In case it is not clear yet, My is a bunch of stateless operations that offer functionality already available in the framework. It is obvious the feature was added to lure VB6 devs that have not yet moved to .NET, but is My really helping them in the long run?

Application events as a concept are a nice idea. Will I use them in VB? Unfortunately the answer is no. Not only I am not too fond of having to give up my own Sub Main, but more importantly they will not be supported in CF 2.0

I haven't made my mind up on whether I like the 3rd part of My. On the face of it, it seems dirty, but only time will tell.

To finish off with a sweeping comment on the whole of the My feature: it is nowhere near in the same league as refactoring (that will not be part of Whidbey) and I would like to talk to the person that was responsible for prioritising these features (not that it will happen, but it doesn't hurt to ask:-).

I had written the above and then came across a post with a similar ending to mine.

More Windows Mobile 2005 Details Emerge

Wed, November 3, 2004, 12:29 PM under MobileAndEmbedded
If you are PocketPC enthusiast you might be interested in Windows Mobile 2005 (codename magneto).

There are some details about it here [found the link via this (Greek) site]

I will not VOTE!

Tue, November 2, 2004, 12:53 PM under Personal
...because I am not an American and I live in the UK anyway! Sorry couldn't resist this entry given all the encouragement to vote from our American blogging friends :-)

May the best man win.

In other news the score is currently Arsenal 1-0 Panathinaikos. Hmmm, should I support the rivals of Manchester United or one of the rivals of PAOK? I'll have to go with the Greek team I guess...

Normal service will resume soon