Monday, November 15, 2010

Differences between enum in C# and C/C++


Recently I encountered a confusing situation that took me by surprise while porting some old, well-proven C++ code to C#: the languages treat enumerated types differently. In C and C++, an enum defines a value type that represents a restricted set of values. An enum type can be declared just about anywhere before it is used, including statement blocks.

In C#,  an enum defines a class (i.e. types are classes), meaning it can be declared only at the namespace or class level; it cannot be defined in a statement block within a method as it can in C++. If you try, Visual Studio issues an error not about the enum definition itself, but instead at the opening brace of the method, stating '} expected' rather than something useful like 'enum cannot be defined at statement level' or even 'invalid statement'. Another unintuitive error message brought to you courtesy of Microsoft.

So if you're a C++ programmer learning C#, beware this trap. It's easily fixed by moving (and naming or renaming) your enumeration to a less narrowly scoped portion of your module, but it's annoying and unwelcome, nonetheless.

Monday, September 20, 2010

Mobile Device Emulator Error on Windows 7: No VPC network adapters enumerated

After upgrading from Windows Vista (pronounced fiasco) to Windows 7 (OMG, there is life after XP!) and reloading everything because there was no migration path (probably for the best anyway), the Windows Mobile device emulator I was using could not be configured with a network connection.

Several articles were well-written and helped me to understand that it could have been something other than missing the Virtual Machine Network Services driver that was the source of the error (which was not my problem). Brian Peek's Windows Virtual PC and the Microsoft Device Emulator article was a excellent piece that led me to try other debugging perspectives. Ben Armstrong's (Virtual PC Guy's Blog) Fixing broken virtual networking was concise and gave me other clues about dealing with the virtual network driver. Many thanks to them for sharing their experiences.

I tried both solutions and neither fixed the problem. What finally worked was getting to the emulator's connection settings through Visual Studio, since the options I needed were disabled within the emulator itself. Go to Tools > Options > Device Tools > Devices, pick a preferred emulator, click the Properties... button, then the Emulator Options button there. On the Network tab, I added a check to the Enable NE2000 PCMCIA network adapter and bind to: checkbox. The critical step was selecting the actual connected network card - not the Connected Network Card option - in the network adapters dropdown box.

Next time I started the emulator, it saw the network adapter and was able to use it. Without selecting the actual network card, the emulator must try to use a hidden, disconnected network adapter (I have both Ethernet and WiFi network adapters in my notebook, both with virtual network services enabled) and fails to see the connected one, hence the notorious error:


No VPC network adapters enumerated or no host network adapter with provided MAC address found


I tried some other solutions, such as replacing the virtual machine network services driver with the one from Virtual PC 2007. It didn't work either, so I uninstalled and reinstalled the VMNS driver that came with Windows 7's Virtual PC. I also cleared the emulator's saved state several times during my ordeal.

Obviously this workaround to the bug in the VM's network device driver has the drawback that you have to reconfigure your network connection if you change network adapters. But at least it got me working again.

For reference, the development platform I got this working on is Windows 7 32-bit Tablet PC with 2 GB RAM, 100GB hard drive, 1.7 GHz CPU and Windows XP Mode with Vista/7 Service Pack. I use Visual Studio 2005 SP2 with the Window Mobile 5 Pocket PC emulator from the Microsoft Windows Mobile 5 SDK. I do a lot of industrial handheld computer development.

Thursday, June 10, 2010

Error: ShowDialog exits immediately

I was trying to implement a WinForm login class called from a menu navigation class, but when I called ShowDialog(), it was exiting immediately without displaying the window or setting the DialogResult code. It was working the first time through the loop, but subsequent calls always failed. I searched all over the 'net for answers without success; in the end, I had to trace through my program a few lines at a time in the debugger until I found the culprit.

Watching the behavior of the preparation call to Login.ShowDialog() resulted in everything appearing normal the first time. Later, the Owner property would not allow assignment - no error, but the value stayed null - and calling ShowDialog() would return immediately with the default value of DialogResult.None. My Load event was even being called as expected. To me, this appeared to be working incorrectly. It turned out to be not incorrect, but undefined behavior I was seeing.

As the stereotypical engineer, I nearly outsmarted myself by designing a library of classes that would handle the details of performing their appropriate menu operations and allow me to define the menus declaratively. One of the classes was responsible for calling a named method and instantiating its type object through reflection if needed. To allow a ShowDialog() method call, the .NET Framework requires the object to be manually disposed afterward. I got fancy and added code to call Dispose() on the object automatically if it was a Form. But...some of my called methods were part of my active menu navigation class, which was itself a Form. When the menu operation was executed, my navigation class got destroyed, so I was clobbering myself.

The resolution was to be careful to not dispose of the class I was actively using. Assigning a disposed Form as the owner of another Form is undefined, pointless, and creates bizarre results, as I so painfully found. Fixing this issue solved the inconsistent behavior. I'm deservedly embarrassed by my mistake, but wiser for it.

If this saves somebody else the inconvenience I experienced to track down this problem, then it will have been worth my time to share this story. Leave me a comment if this helped you in any way.

Friday, January 15, 2010

Installing NUnit with Visual Studio 2005 on Windows Vista

This article isn't about how to use or configure NUnit, it is simply about getting it installed. The short version is listed at the end of this article.

Running Visual Studio 2005 on a Windows Vista platform, the documentation on the NUnit project web site was a bit anemic and left me perplexed. I posted my notes and experience here to help the next programmer who falls into the same trap of using inadequate documentation and having no previous experience with the product.

Getting started with the NUnit testing framework was rather like touching an electrified fence: the shock certainly woke me up. Now, don't think I don't like the package and the effort that went into it. I certainly want to thank the authors for putting together a very useful software framework that improves the quality of my code. On the other hand, it would be nicer if it were easier to get working or at least had some accurate installation instructions somewhere. To the best of my ability, here are those instructions.

The download page was pretty clear about what package you should use. Since I wanted to install on Windows and wasn't going to be developing NUnit itself, I picked the Windows binary Installer package. At the time this article was written, NUnit 2.5.3 was the current production release, so I downloaded the "win" installation archive, NUnit-2.5.3.9345.msi, and ran it on my development machine. I picked the Typical installation and got what I thought I needed. Seemed simple enough.

Following the text on the Installation page, I got to the Configuration section (about half a page) before the fog started setting in. The document mentions the configuration files are different depending on the NUnit executable you run. Personally I think this belongs in a different section of the document, but I could go back and look at it again later, so I just overlooked it for now.

The Installation Verification really threw me for a loop. It states:
Verify that the installation has worked successfully by running the NUnit gui and loading and running NUnitTests.nunit. All tests should pass.


Warning! Misleading Documentation Alert! OK, it's elementary that I can run the GUI NUnit by going to Start->NUnit 2.5.3->NUnit. Now I just needed to find NUnitTests.nunit. No dice. After searching fruitlessly through every folder the installer created, I deduced that somebody simply forgot to include the file in the installer archive. Oh well, mistakes happen. I went back to the web site and downloaded the previous version. Uninstalled 2.5.3 and installed 2.5.2. *#&*@^! Same problem. The file didn't exist in either of the latest packages, so I thought. Grrr!

After a brief email exchange with the project administrator, Charlie Poole, it turns out that performing the Typical install, the file is not available. Only if you install the Unit Tests for NUnit under .NET 1.1 does the noted file get installed. This is confusing and a revision of the documentation or installer is under consideration. I have to say this was very responsive and indicative of the quality of the package as I saw so far.

Well, I just skipped the verification and tried one of the samples. Curiously, there were no *.nunit files to be found anywhere. Maybe they were just for the GUI? I hadn't found it in the documentation so I moved on to compile a sample.

I use C# most of the time, so I used one of those samples. The samples\csharp directory contained several different tests organized under what appears to be a Visual Studio Solution so I opened CSharp.sln. OK, VS had to convert it to my version, so I let it and it didn't complain. Built the solution and got an error in MoneyTest.cs:

The type or namespace name 'Framework' does not exist in the namespace 'NUnit' (are you missing an assembly reference?)




I checked the references; no, it was there. But there was a warning label on the icon. Looking at its properties, the reference had no path and no version!

Now was Visual Studio giving me problems? I clicked on the project icon, added the reference again - at least I was able to pick it off the .NET reference list. It was named nunit.framework, not NUnit.Framework, so that didn't look right. But, no change, the reference still showed the warning label. @$#@#&%#@!

I removed the existing reference and added the reference again. Now it sorta looked right that the warning label was gone. Build, and the projects were compiled. I launched the NUnit GUI application. Selected Open Project... and browsed to the csharp/money directory. Nothing. Really? No, nothing. Drilled down into bin/Debug and find a couple .dll files, but still no *.nunit files. Tried loading the cs-money.dll assembly directly and I saw the tree of tests. That was promising. So I clicked the Run button and a green progress bar filled the status area.



Success!? Yes, no, maybe? Yes, I'll call it success.

My suspicion was the .dll assembly contained all the information an NUnit project file would have, but I didn't locate the documentation to prove it. Trial and error is a heck of a poor way to find out. Moral: bad documentation doesn't make for good testing. Your mileage may vary :-/.

Here's the short version of all this:
  1. Download the NUnit installer package.

  2. Run the installer.

  3. Skip the Installation Verification step because the files weren't installed.

  4. To create and use NUnit tests with a new project, add a reference to the nunit.framework.dll library to the project.

  5. To use NUnit with the sample projects, remove the existing nunit.framework.dll library references first. Add a reference to the newly installed library to the projects.

  6. Don't bother looking for *.nunit files. Or do a full install.



It's difficult to be grateful when you're annoyed. But at least I was running and demonstrated the framework will actually do what it's told, once I figured that out.

The End

Friday, January 8, 2010

Revised WorkerThread class and Bug in EventWaitHandle.WaitOne() in .Net CF 2.0

The WaitOne(int millisecondsTimeout, bool exitContext) method of the ManualResetEvent (based on EventWaitHandle) class allows waiting for a synchronization flag to be set, but timing out if it does not. On the .Net Compact Framework (.NetCF) 2.0, calling this method with exitContext set to true throws an ArgumentException exception. The fix is to always set exitContext to false.

How I got into this was researching .Net worker threads. There was a very good article written by Juval Löwy, titled Working with .NET Threads, and provided a useful wrapper class, named WorkerThread, to make managing threads easier in your application. Thank you, Juval!

I use .NetCF frequently and, as usual, found some incompatibilities I had to correct before the WorkerThread class worked on that platform. The revised and better-documented WorkerThread for .NetCF 2.0 is listed below. Even after rewriting for the methods missing in the compact framework, I ran across a bug in .NetCF 2.0 that prevents the class from working properly.

The wrapper class relies on several synchronization constructs in order to provide safe access to its functionality across threads. One such case is where an extra integrity check attempts to determine that the thread is actually running, in the code that implements the IsAlive property. As originally coded, it was:


public bool IsAlive
{
get
{
Debug.Assert(m_ThreadObj != null);
bool isAlive = m_ThreadObj.IsAlive;
bool handleSignaled = m_ThreadHandle.WaitOne(0,true);
Debug.Assert(handleSignaled == ! isAlive);
return isAlive;
}
}


The problem appears in the call to WaitOne(0,true). While it compiles fine, at runtime it throws an ArgumentException error instead of ignoring or saving & restoring the synchronization context (a completely different concept than the thread synchronization I'm writing about here). Simple to fix, but maddening to diagnose.

The other minor issues I fixed were:

  • No IsAlive property on the .NetCF Thread class. Reference was commented out. I added a new instance variable, m_IsAlive, to emulate the missing property.

  • No Join(TimeSpan timeout) method on the .NetCF Thread class. Translated that method to use Join(int millisecondsTimeout) instead.

  • Fixed IsAlive property code to avoid the ArgumentException error, as mentioned above.

  • Added a Yield() method to relinquish the processor to other threads as an alternative to using the more cryptic Thread.Sleep(1).

  • Added an overridable Work() method to allow this class to be inherited instead of copied and modified. Replace Work() in your derived class to implement your processing.

  • Modified the Run() method to call Work() and automatically manage the IsAlive property.



As a way to pass on the bits of knowledge I've gained from this exercise, here is the final source for the .NetCF 2.0 WorkerThread class:


////////////////////////////////////////////////////////////////////////////////
// File.......: WorkerThread.cs
// Author.....: Edward F Eaglehouse
// Date.......: 11/21/2009
// Notes......:
// Adapted for .NetCF 2.0 from the WorkerThread class by Juval Lowy in his
// article, Working with .NET Threads. The full article text can be found at
// http://www.devx.com/codemag/Article/17442/0/page/1.
////////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace gltech.trackaway
{
///
/// Class that implements a separate worker thread.
///

///
/// Based closely on the WorkerThread wrapper class described in the
/// article Working with .NET Threads,
/// by Juval Löwy. Modified so it works with the .NET Compact Framework.
///

public class WorkerThread : IDisposable
{

#region Protected Members

///
/// Synchronization construct for signalling completion of the thread.
///

protected ManualResetEvent m_ThreadHandle;

///
/// Contains a reference to the uninheritable underlying Thread object.
///

protected Thread m_ThreadObj;

///
/// Flag to indicate that thread processing should be stopped.
///

protected bool m_EndLoop;

///
/// Synchronization construct to protect the EndLoop flag.
///

protected Mutex m_EndLoopMutex;

///
/// Flag to indicate the thread is actively running.
///

protected bool m_IsAlive;

#endregion

#region Constructors

///
/// Initialize a new instance of the WorkerThread class.
///

public WorkerThread()
{
m_EndLoop = false;
m_ThreadObj = null;
m_EndLoopMutex = new Mutex();
m_ThreadHandle = new ManualResetEvent(false);

ThreadStart threadStart = new ThreadStart(Run);
m_ThreadObj = new Thread(threadStart);
m_ThreadObj.Name = "Worker Thread";
m_IsAlive = false;
}

///
/// Initialize a new instance of the WorkerThread class.
///

/// True to launch the thread immediately; otherwise, false.
public WorkerThread(bool autoStart)
: this()
{
if (autoStart)
{
Start();
}
}

#endregion

#region Properties

///
/// Get the underlying Thread object.
///

public Thread Thread
{
get
{
return m_ThreadObj;
}
}

///
/// Get the thread completion synchronization object.
///

public WaitHandle Handle
{
get
{
return m_ThreadHandle;
}
}

///
/// Get the indicator that the thread is active.
///

public bool IsAlive
{
get
{
Debug.Assert(m_ThreadObj != null);
//bool isAlive = m_Thread.IsAlive;
bool isAlive = this.m_IsAlive;
//bool handleSignaled = m_ThreadHandle.WaitOne(0, true);
bool handleSignaled = m_ThreadHandle.WaitOne(0, false);
Debug.Assert(handleSignaled == !isAlive);
return isAlive;
}
}

///
/// Get or set the indicator that processing should stop.
///

protected bool EndLoop
{
set
{
m_EndLoopMutex.WaitOne();
m_EndLoop = value;
m_EndLoopMutex.ReleaseMutex();
}
get
{
bool result = false;
m_EndLoopMutex.WaitOne();
result = m_EndLoop;
m_EndLoopMutex.ReleaseMutex();
return result;
}
}

///
/// Get or set the debuggable thread name.
///

public string Name
{
get
{
return m_ThreadObj.Name;
}
set
{
m_ThreadObj.Name = value;
}
}

#endregion

#region Public Methods

///
/// Launch the thread.
///

public void Start()
{
Debug.Assert(m_ThreadObj != null);
//Debug.Assert(m_ThreadObj.IsAlive == false);
m_ThreadObj.Start();
} // Start()

///
/// Overridable method that implements the processing to be done.
///

public virtual void Work()
{
int i = 0;
while (EndLoop == false)
{
Debug.WriteLine("Thread is alive, Counter is " + i);
i++;
}
} // Work()

///
/// Destroy this WorkerThread instance.
///

public void Dispose()
{
Kill();
} // Dispose()

///
/// Notify the processing loop to stop.
///

public void Kill()
{
//Kill is called on client thread - must use cached object
Debug.Assert(m_ThreadObj != null);
if (IsAlive == false)
{
return;
}
EndLoop = true;
//Wait for thread to die
Join();
m_EndLoopMutex.Close();
m_ThreadHandle.Close();
} // Kill()

///
/// Blocks the calling thread until this thread terminates.
///

public void Join()
{
Debug.Assert(m_ThreadObj != null);
if (IsAlive == false)
{
return;
}
Debug.Assert(Thread.CurrentThread.GetHashCode() !=
m_ThreadObj.GetHashCode());
m_ThreadObj.Join();
} // Join()

///
/// Blocks the calling thread until this thread terminates or the
/// specified time elapses.
///

/// Number of milliseconds to wait.
///
public bool Join(int millisecondsTimeout)
{
TimeSpan timeout;
timeout = TimeSpan.FromMilliseconds(millisecondsTimeout);
return Join(timeout);
} // Join(int millisecondsTimeout)

///
/// Blocks the calling thread until this thread terminates or the
/// specified time elapses.
///

/// TimeSpan set to the amount of time to wait.
///
public bool Join(TimeSpan timeout)
{
int timeout_ms = (int)timeout.TotalMilliseconds;

Debug.Assert(m_ThreadObj != null);
if (IsAlive == false)
{
return true;
}
Debug.Assert(Thread.CurrentThread.GetHashCode() !=
m_ThreadObj.GetHashCode());
return m_ThreadObj.Join(timeout_ms);
} // Join(TimeSpan timeout)

///
/// Suspend this thread to allow other waiting threads to execute.
///

public void Yield()
{
// Yield processor to other threads, even ones at a lower priority.
Thread.Sleep(1);
} // Yield()

#endregion

#region Protected Methods

///
/// Do the processing defined by this thread.
///

protected void Run()
{
try
{
m_IsAlive = true;
Work();
}
finally
{
m_IsAlive = false;
m_ThreadHandle.Set();
}
} // Run()

#endregion

}
}