Tuesday, 20 November 2012

DateTime.ParseExact can be misleading

Last night, I was made aware of a crash in our Payslips for PAYE Tools program that occured pretty much every time it ran.

It turns out the user had changed the short date format on their system, so it included either a . or a – as the separator.

I had this line in my code:

Date = DateTime.ParseExact(value, "dd/MM/yyyy", null);

While this looks like it might do the right thing, it turns out it doesn’t as I didn’t use the invariant culture for the conversion.  The word exact is a bit misleading, as I’d assumed (incorrectly) that / was a character.  In fact, it’s replaced with the date separator, and no longer matches the string that came out of the database with a /

Tuesday, 13 November 2012

Be very careful saving data in Windows 8

Windows 8 presents a number of new challenges for developers.

My challenge today is how can I save what the user is doing, and not lose it.

Best practice for Windows 8 apps suggests you save early, and often.  From the time a user closes your app you have about 10 seconds until it’s definitely not running.  For those of you who aren’t totally up to speed on the details of the Windows Store Application Lifecycle I suggest you have a look here first.

Now, the problem is in that article, on the section on App Close

App close

Generally, users don't need to close apps, they can let Windows manage them. However, users can choose to close an app using the close gesture or by pressing Alt+F4. You can't include any UI in your app to enable the user to close your app, or it won't pass the Store certification process.

Given the above, you can see that there is no way to be notified of a close event, however your OnSuspending event will still fire, after about 5 seconds.

So, assuming you busily began to save when you’re app received the VisibilityChanged event, you have maybe 5 seconds left to save the remainder of your state when you get to OnSuspending.

I say maybe, because, if you’re really unlucky, you’ll find that the user restarted your application from the start menu, after beginning your OnSuspending code.  In that case, your currently running thread will be terminated and your app will restart.  The file you were in the middle of saving could now be in any state.

If you don’t believe me, you can read the details here

Saving the application data to file in the Application.OnSuspending method does not work?

In a nutshell, this quote from the bottom of the thread sums up the problem
"To summarize, if the user closes the app and then immediately restarts before the first instance has finished closing then the first instance is forcibly terminated so the user runs in a clean state."

So, how do we build an application to demonstrate the problem?  First, in App.xaml.cs, wire up the VisibilityChanged event when you create your root frame.

Window.Current.VisibilityChanged += Current_VisibilityChanged;
this.Suspending += OnSuspending;

Next, implement the event handler like this and add a couple of members.


Task currentSaveTask;
void Current_VisibilityChanged(object sender, WIndows.UI.Core.VisibilityChangedEventArgs e)
{
if (!e.Visible && currentSaveTask == null)
{
CurrentSaveTask = SaveOurData();
}
}
async Task RenameFile(string tempFile, string newName)
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile sf = await localFolder.GetFileAsync(tempFile);
await sf.RenameAsync(newName, NameCollisionOption.ReplaceExisting);
}

async Task WriteData(string filename, string content)
{
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
// on my machine, this is C:\Users\Tony\AppData\Local\Packages\2da24013-8fd9-49f2-8067-778dece884d6_6j3fz8tfj8x4m\LocalState

StorageFile sf = await localFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);

using (Stream s = await sf.OpenStreamForWriteAsync())
using (TextWriter output = new StreamWriter(s))
{
output.WriteLine(content);
}
}

async Task BeginSaving()
{
await WriteData("startup.txt", "We started saving");
}

async Task ContinueSaving()
{
await WriteData("temporary.txt", "The data file is incomplete");
}

async Task FinishSaving()
{
await WriteData("temporary.txt", "The data file was written successfully");
}

async Task SaveOurData()
{
await BeginSaving(); // show some progress to the user.
await Task.Delay(5500); // simulate extra work
await ContinueSaving();
await Task.Delay(4000); // simulate still more work.
await FinishSaving();
await RenameFile("temporary.txt", "final.txt");
currentSaveTask = null; // remove reference to our pending save
}


This writes a file in to our local storage, named startup.txt, and then delays long enough to guarantee we’re in the Suspend code, it then creates a file temporary.txt, delays a little longer, and finally writes the finished version of the temporary.txt file.


Finally it proceeds to rename the file to final.txt, and cleans up the handle to the outstanding task.


Now implement our OnSuspending handler like this:


 


async private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
if (currentSaveTask != null) await currentSaveTask;
// you may want to use Task.WhenAll here to rendezvous multiple tasks...
// Task[] OutstandingSave = new Task[] { currentSaveTask };
//if (OutstandingSave[0] != null)
//{
// await Task.WhenAll(OutstandingSave);
//}
deferral.Complete();
}


This code waits for the currentSaveTask we kicked off if it exists.





Testing


To test this, do the following.


Fire up your app, and and open a window to wherever your App’s StorageFolder.LocalFolder resolves to.


Now press F4 on the app, to close it.


You should see a startup.txt file appear, followed after about 5.5 seconds a temporary.txt file appear. When you see that appear, quickly press the windows key, and click to restart your app.


You’ll notice that the remainder of the code never executes, and when you examine temporary.txt, it will contain “The data file is incomplete”.


Takeaway


If you were saving directly to a file (in XML format) and hadn’t yet completed by the time you relaunched, your file would be incomplete or corrupt.  This method allows you to check that the temporary.txt file does not exist at startup.  If it does exist, you can be pretty certain that final.txt file is incomplete.  Of course, temporary.txt file may be incomplete as well, so you’ll need to code in an additional step to allow you to check that it too is complete, (possibly by renaming to another intermediate file, temporaryfinal.txt?)

Thursday, 1 November 2012

HP Machines and Windows 8

I’ve had a bad 24 hours.  I’ve been trying to get started developing for Windows Phone 8, and as a result of the new outlandish hardware requirements to do so have had to purchase a new PC.

So, I wandered down to Curry’s and picked up an  HPPavilion g6-2241sa 15.6 Laptop – Blue for £350.  I then had to get the windows pro pack to enable Hyper-V, (which I still haven’t, at the time of writing this, managed)

Alas, I’ve stumbled into the problem that Windows Update on HP machines doesn't actually work very well (if at all).  The big 190 MB update that needs to be done locks up after reboot at 13%

After nearly 12 hours talking to support, I came across this:

http://support.microsoft.com/kb/2777330

What I did was:

go to the windows update site, and download the updates manually: KB2764870, KB2761094, and 2756872 as well as delmigprov.exe

http://www.microsoft.com/en-us/download/details.aspx?id=34908

I then ran delmigprov

did the clean boot thing

copied the files to the desktop

and then went to device manager, and uninstalled all devices that might cause a problem (2x network, card reader, 2xaudio, and web cam).

I also manually stopped the audio services in case it was the IDT audio.After running the first 2 kb updates, I needed to reboot.

Alas, that meant I had to remove all of the devices again, and stop the services after they were installed.

Now my machine has finally booted back into windows!

I am now going to create another system restore point

Since then, I’ve added another 5 windows updates, but this time without disabling the devices.

And now another restore point, and finally install of pro-pack.

All of this seems to have worked, and I’m finally up and running after only 19 hours of work.

If this has saved you time, please consider purchasing some of our software at http://www.wieser-software.com/

Wednesday, 31 October 2012

Updating to Windows 8

Updating ought to have been easy, but I found it incredibly frustrating.

First, I went to the upgrade site, but after getting all the way through the purchase process, it stated that the upgrade wasn’t for commercial use.

OK.  Off to Curry’s to reserve a DVD which also prevents me having to download the whole thing: Get Windows 8 upgrade on DVD from Currys at £49.99 and apparently doesn’t have the commercial restriction, a premium of £25.00.

When I got there I started looking at a new laptop as well, but that’s another story.

So, I’m now installing from the DVD I purchased.

The first thing I need to do is uninstall the incompatible apps (some Dell stuff, an Intel USB3 driver?, and Security Essentials!?) followed by a reboot.

I chose to keep my existing, files, programs and settings.

After quite a long delay, my machine installed devices, then spent quite awhile longer preparing. 

Another reboot, and “Moving your settings” was the next task.

Following that, a personalize choice, followed by connecting to the network via wireless (I’ll do that later).  I then chose express settings, and entered my previous admin password, and chose sign in without a Microsoft account.  After “Finalising your settings” a disconcerting black screen before “Hi” Finally appeared along with the W8 intro stuff.

It eventually booted into W8, so after the initial confusion about licensing, not too bad.

Installing the Windows Phone 8 SDK was a different matter though.  At this moment, still not done, so although I have Windows 8 Pro, it doesn’t do what it needs to.

Wednesday, 17 October 2012

Windows 8 Selected Item Styles in a GridView control

While building our latest app, Travel Advisories I noticed that our selected items didn’t look a lot like the selected items elsewhere on Modern UI Style Apps.

My app was generating selections that looked like this:

transparent

The selection box has the tick, but it isn’t an outline, and it’s completely filled with the color.

Eventually, I worked out that this was caused by my xaml for the ItemTemplate

<GridView.ItemTemplate>
<DataTemplate>
<Grid Width="400" Margin="3" HorizontalAlignment="Left" >
<TextBlock Margin ="20,0,0,0" FontSize="32"
HorizontalAlignment="Left" VerticalAlignment="Top"
Text="{Binding Country}" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>


You’ll note that we don’t set any background and leave it transparent.  Having looked at some sample code, I found that most of the samples were setting a background color for the ItemTemplates, so changing the background of the grid to Black makes it look like this:


opaque


Now you can see that we have a completely black background, and the corner marked with the tick, much like the other samples.  But that still isn’t the look I was after.  What I wanted was a totally transparent background showing the background behind the text.


To accomplish that requires delving into the default ItemContainerStyle and a trip into blend to do it, so do the following



  • Open the project in blend

  • Right Click on your GridView in the Objects Window

  • Expand Edit Additional Templates

  • Expand Edit Generated Item Container

  • Select Edit a copy, and edit the 290 additional lines of code

The one line of code your looking for looks like this


<Rectangle x:Name="SelectionBackground" Fill="Transparent" Margin="4" Opacity="0"/>


Where the Fill is set to a StaticResource Binding.


Having made that change, we now get the desired result:


semitransparent

Using the Snipping tool on Metro Style Apps on Windows 8

I was just about to start another blog post, and realized I had no idea how to get a snapshot of a portion of a metro Modern UI Style App screen.

The snipping tool works great, but there isn’t any way to actually see the metro app at the same time, (or so I thought, until I discovered the secret).

First start the snipping tool, by pressing the windows key, and typing snipping.

snipping

Next start your Microsoft Store App you want a snapshot of.

Now, the magic.  Press Control+Print Screen and the Snipping tool pops back on top

startsnipping

Finally, drag out your snipping area, just like you would on a desktop app and save the results.

Wednesday, 12 September 2012

On Windows 8 things aren’t always what they seem

I’ve been busy the last couple of months getting started on Windows 8.

Yesterday, I was trying to get data into a WriteableBitmap, and was a bit confused by what you could actually do with an IBuffer.  The interface only contains two methods, neither of which hands off the contents of the buffer.

Charles Petzold has an article that describes his attempts to get access to the buffer, and shows that C++ code isn’t all that much faster than the C# method of writing to a stream.  After reading his blog post, I discovered that I should have added a using statement to the top of my code to get the extension methods.

using System.Runtime.InteropServices.WindowsRuntime;


Once that’s been done, you discover that there are actually quite a few extension methods that work on IBuffer, and a promising one was


public static void CopyTo(this byte[] source, int sourceIndex, 
IBuffer destination, uint destinationIndex, int count);



I’ve been there, done that and got the t-shirt.  Don’t use this function for random access into the IBuffer.  I wrote the following loop:


bmp = new WriteableBitmap(240,240);
int e = bmp.PixelHeight * bmp.PixelWidth * 4;
byte [] twopixels = new byte[8];

int startCount = System.Environment.TickCount;
buf = bmp.PixelBuffer;

for (int j=0;j<100;j++)
// now run the loop 100 times.
for (int k=0;k<e;k+=8)
{
twopixels.CopyTo(0, buf, k, 8);
}
Debug.WriteLine(string.Format("{0} ticks elapsed", System.Environment.TickCount - startCount));


To my surprise, that code was ten times slower than this code:


byte [] colors = new byte[8];
bmp = new WriteableBitmap(240,240);
int e = bmp.PixelHeight * bmp.PixelWidth * 4;
byte [] Pixels = new byte[bmp.PixelHeight*bmp.PixelWidth*4];

int startCount = System.Environment.TickCount;
buf = bmp.PixelBuffer;

for (int j=0;j<100;j++)
// now run the loop 100 times.
for (int k=0;k<e;k+=8)
{
System.Buffer.BlockCopy(colors, 0, Pixels, k, 8);
}

using (Stream pixelStream = buf.AsStream())
{
await pixelStream.WriteAsync(Pixels, 0, Pixels.Length);
}
Debug.WriteLine(string.Format("{0} ticks elapsed", System.Environment.TickCount - startCount));


So, for whatever reason, byte.CopyTo is extremely inefficient.  Looking at the code, it appears that there is a lot of checking happening to the parameters, and also a call to Marshal.Copy deep inside the checks.


ADDENDUM


Having posted this I decided to go back and modify the slow version.


For reference, to run the code above 100 times took 4633 ticks for the first method, and 312 ticks for the second.


So, to try one last time, I did this:


bmp = new WriteableBitmap(240,240);
int e = bmp.PixelHeight * bmp.PixelWidth * 4;
byte [] twopixels = new byte[8];
int startCount = System.Environment.TickCount;
buf = bmp.PixelBuffer;
byte[] Pixels = buf.ToArray();
for (int j=0;j<100;j++)
// now run the loop 100 times.
for (int k=0;k<e;k+=8)
{
System.Buffer.BLockCopy(twopixels, 0, Pixels, k, 8);
}
Pixels.CopyTo(0,buf, 0, Pixels.Length)
Debug.WriteLine(string.Format("{0} ticks elapsed", System.Environment.TickCount - startCount));


To my surprise, this was the fastest of all of them taking only 234 ticks, an improvement of 33%!