Saturday, April 18, 2015

Why does my .NET app lock up with tasks?!

Such a silly mistake!  I'm pretty sure I even did this before in the past.  I was getting so frustrated that the async/await pattern was completely letting me down.  Tasks were never finishing, or just not consistently at all.

I'm using a cool pattern where you spin up lots of work (iterating a collection and creating tasks per item), then wait on all tasks at once.  It's so great because if some of the early tasks end before you start waiting on them, it makes no difference.  Code won't continue until all are done and you don't need to specially handle the ones that finish early.
var tasks = new List<Task>();
foreach( var item in iter )
{
    var tsk = DoThingAsync( item );
    tasks.Add( tsk );
}
Task.WaitAll( tasks.ToArray() );
Notice that you don't await the DoThingAsync() call.  This is intentional.  If you await here, then you won't move onto the next item in the collection until it completes.  Instead, you add it to the collection and use it as a group.  The problem is the method that I was using.  WaitAll() is the wrong method!  So deceptive.  None of my code would reliably complete and I couldn't figure out why.

The problem is that if you use WaitAll, the thread blocks until all tasks finish.  This could be fine in some cases, but if your tasks require the synchronization context (such as the HttpClient), they will lock up.  The simple change is just to the last line:
await Task.WhenAll( tasks.ToArray() );
Now, perfection!  The await completes when all tasks complete, and nothing is blocked.  Such beautiful simplicity, such a frustrating mistake!

Friday, March 13, 2015

Programmatically joining WiFi network from Xamarin Android

I'm currently working on a project where I need to programmatically join a WiFi network from a Xamarin Forms Android app.  It turns out to be pretty simple.  I take the extra step of checking to see if the network is in the list first, though I'm not sure it's necessary.  It also takes care of a few more things:
  • SetWifiEnabled makes sure that the radio is turned on
  • UpdateNetwork checks to see if the network for the given SSID has changed.  Could happen if you used the same SSID on a new router maybe
  • Disconnect takes you off of whatever network you might be associated with
  • EnableNetwork with true makes sure that the given SSID is active and that no others are
  • CreateWifiLock prevents the OS from disabling the radio or putting it in low-power mode
  • SaveConfiguration makes the network changes permanent in the list of networks
It was so much easier than I expected!
public bool JoinWifi(string ssid, string key)
{
try
{
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.Ssid = String.Format("\"{0}\"", ssid);
wifiConfig.PreSharedKey = String.Format("\"{0}\"", key);
WifiManager wifiManager = (WifiManager)GetSystemService(Context.WifiService);
wifiManager.SetWifiEnabled(true);
 
// Get or add network to known list
int netId;
var network = wifiManager.ConfiguredNetworks.FirstOrDefault(cn=>cn.Ssid == ssid);
if( network != null ) netId = network.NetworkId;
else
{
netId = wifiManager.AddNetwork(wifiConfig);
wifiManager.SaveConfiguration();
}
 
// Make sure network hasn't changed
wifiManager.UpdateNetwork(wifiConfig);
var currConn = wifiManager.ConnectionInfo;
if( currConn != null && currConn.NetworkId != netId )
{
wifiManager.Disconnect();
wifiManager.EnableNetwork(netId, true);
wifiManager.Reconnect();
}
 
// Make sure system doesn't save power by disabling WiFi
wifiManager.CreateWifiLock(Android.Net.WifiMode.Full, "myLockId");
return true; 
}
catch( Exception x) {
return false;
}
}

Saturday, January 31, 2015

Windows Phone App: N'Ko Writer

Does that make any sense to you?  Perhaps not, unless you live in countries like Guinea, Mali, or Côte d'Ivoire in West Africa.  For those people, the N'Ko alphabet is a written language that enables people to put their words down on paper.  Unfortunately, modern technology hasn't kept pace with any but the top 40 or so languages around the world.  For this reason, I wrote N'Ko Writer -- a Windows Phone 8.1 app.  N'Ko Writer enables people to compose text using a custom keyboard.  Since Windows Phone doesn't support system-wide custom keyboards, this is only accessible within the app itself.  Once you enter the text though, you can use the standard sharing ability of Windows Phone to send the text to email, SMS/messaging, Twitter, Facebook, or any other apps that support the share function.  I hope this helps the people of West Africa to communicate in their own written language!

The app is free and available today.  Please take a look and spread the word!

Resources:

Saturday, October 25, 2014

OneDrive File Browser for Windows Phone

I finally got around to update my OneDrive File Browse Task for Windows Phone 8.1 Silverlight projects.  There is newer OneDrive functionality now, but if you are just looking for a quick upgrade, then this may do the trick.  It's also cleaner than redirecting to the OneDrive app to browse files.  I hope it helps you!

Link: https://www.nuget.org/packages/ArianKulp.SkyDrive.BrowseTask/1.5.0

Friday, October 24, 2014

Windows Technical Preview - Update build - Error 0xc1900101 - Fixed!

After attempting around ten installs of the new Windows 10 build the other day, and reading many forums posts, I've finally got it working!  The posts varied somewhat, but mostly seemed to center on devices being the problem.  Like disconnect all external devices, or run the upgrade from Safe Mode.  I tried everything I could think of, until I noticed one thread mentioning free hard drive space.  I had under 20GB free on my drive.  I spent some time and got it to 50GB, and low and behold the update worked!  I'm not on the latest build.  Finally!

If you keep getting the 0xC1900101 error with the build upgrade failing, FREE UP DRIVE SPACE!

Friday, August 8, 2014

Opening large images in Live Photo Gallery

I've just learned that after copying lots of big photos from my Lumia 1020 to my network storage device Live Gallery won't load them anymore.  Just lots of gray boxes!  Just a little bit of searching brought me to a Microsoft support page that provides instructions on how to fix it.  Very easy fix, though the specific registry location has changed since the article was written.  You actually want to go to:

HKEY_CURRENT_USER\Software\Microsoft\Windows Live\Photo Gallery

to create the MaximumFrameSizeMegapixels key.  Other than that, it works like a charm!  This only seems to matter for network images.  When the photos were local I never had this problem.

Link: http://support.microsoft.com/kb/2725211

Friday, May 30, 2014

Awaitable functions in properties

If you've ever needed to call an asynchronous function from within a property setter, you may have been confused, or at least unhappy with the result.  You know that it needs the "await" operator, but if you add it you'll get an error since it's not even possible to make a property async.

public string Name
{
    get{ return _name; }
    set{ await VerifyAsync(value); RaisePropertyChanged("Name"); }
}

If you don't add await, then you'll get a compiler warning, but you'll also lose the flow that you have.  This will probably result in a notify change event being called before your code finishes running.  This is because if you don't await, the asynchronous call is dispatched to a background worker and your code continues running.  This means that interested parties get events before the value might be truly updated!

public string Name
{
    get{ return _name; }
    set{ VerifyAsync(value); RaisePropertyChanged("Name"); }
}

You might be tempted to wait on it, but in many cases this causes issues with deadlocks, or causes responsiveness issues that the async pattern is trying to fix.

public string Name
{
    get{ return _name; }
    set{ VerifyAsync(value).Wait(); RaisePropertyChanged("Name"); }
}

It turns out that the fix is pretty simple by using a delegate and the Task.ContinueWith method.  This lets you dictate code to run when an async call finishes, without using the await keyword.  Just add your code that needs to run after and you'll know it will be in the right order!

public string Name
{
    get{ return _name; }
    set{
        VerifyAsync(value).ContinueWith((t)=> {
            RaisePropertyChanged("Name"); }
    }
}