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: