Thursday, January 24, 2013

Windows Store Apps with F# (part 2) : async/await


In my last post we created an windows apps and discussed the F# and C#/XAML interoperability. We discovered two issue:
  1. Long running calculations made the UI frees.
  2. The improper handling of the input made the app crash.
The way we deal with issues is an architectural decision. One can choose to have a slim F# library. The only responsibility is to handle the business logic, nothing else. In our case this is a math library. There is nothing wrong with decision, the other concerns are handled at the C#/XAML site by C# developers and XAML designers. We could resolve the first issue by wrapping the calculation in a task and await it. We could solve the input issues by writing a handler that will handle TextBox TextChanged  event.
If this is your decision the post ends here.
Or we could decide to minimize the C# code and solve all issues at the F# site. That is the way we will continue.
We start by where we left last time.
We first fix the second issue.
We delete in the MainPage XAML the last two TextBlocks and add a new one:
<TextBlock Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3"  x:Name="result" Style="{StaticResource FSharp}" />

and add a text wrapper function to a new F# file called Wrapper.
module MathLib.Wrapper
open System
let IsPrimeText text =
let success, number = Int64.TryParse(text)
if success then
if
Prime.IsPrime number then
number.ToString() + " is a prime number"
else
number.ToString() + " is not a prime number"
else
text + " is not a valid number"

Now we can change the OnClick event handler in
private void OnClick(object sender, RoutedEventArgs e)
{
result.Text =
Wrapper.IsPrimeText(inputValue.Text);
}

All the code to handle the text input and displaying the result are now in the wrapper. Text input does not crash the app.

screenshot_01242013_115705

In a real project we could put more logic to del with input in the wrapper functions.

Next we have to deal with long running calculations. The new C# way is to use async/await. so we add async to the OnClick handler. We get a warning.

Warning
The warning tells us that we need to await something, and this should be a Task.

So we create a second F# wrapper:
open System.Threading.Tasks
let IsPrimeTask text =
Task<string>.Factory.StartNew(
fun _ -> IsPrimeText text)

And call this function with await:
private async void OnClick(object sender, RoutedEventArgs e)
{
result.Text =
"start";
result.Text =
await Wrapper.IsPrimeTask(inputValue.Text);
}

When we start the application and check 756771235126757131.

screenshot_01242013_121614

The task is started and we can still update the UI. So the issues are solved.

Remark: This works because it is .NET interoperability. One should use the WinRT the  interface  IAsyncOperation<string>.
private async void OnClick(object sender, RoutedEventArgs e)
{
result.Text =
"start";
IAsyncOperation<string> operation = Wrapper.IsPrimeTask(inputValue.Text).AsAsyncOperation<string>();

result.Text =
await operation;
}

This interface does not seem to be available in the F# library. Fortunately we can not reference a F# Portable Library in a JavaScript App:

Html_FSharp

So this is not an issue at the moment.

Next time we will look for ways to get ride op the event handling code by looking at data binding and MVVM.

Wednesday, January 23, 2013

Windows Store Apps with F# (part 1) : Make things as simple as possible, but not simpler.


During the initial phase of the Windows 8 beta period it was not possible to integrate F# code in a Windows 8 store app. After the final release of Visual Studio 2012 it is possible to create hybrid projects. In this series of posts I want to show you some of the projects I use to experiment with F# and Windows App Store integration.
I will focus on the interoperability and assume that you are able to find resources to learn the details of XAML, Windows 8 store apps and F#.

In the first example we create a simple solution and just add some F# code.
The F# code will determine if a number is a prime number. The App UI should have a text box to enter a value, a button to start the check and a text block to display the result.
We start by creating a blank windows store app:
CreateProject
Open the created main page
MainPage
and start designing the layout of the page.
    <Page.Resources>
<
Style x:Key="FSharp" TargetType="TextBlock" BasedOn="{StaticResource BasicTextStyle}">
<
Setter Property="FontFamily" Value="Verdana"/>
<
Setter Property="FontSize" Value="32"/>
</
Style>
</
Page.Resources>

Next we change the color of the grid and add some columns and rows:
 <Grid Background="#FF8F0A0A">
<
Grid.ColumnDefinitions>
<
ColumnDefinition Width="10*"/>
<
ColumnDefinition Width="200"/>
<
ColumnDefinition Width="100"/>
<
ColumnDefinition Width="300"/>
<
ColumnDefinition Width="20*"/>
</
Grid.ColumnDefinitions>
<
Grid.RowDefinitions>
<
RowDefinition Height="10*"/>
<
RowDefinition Height="50"/>
<
RowDefinition Height="100"/>
<
RowDefinition Height="50"/>
<
RowDefinition Height="20*"/>
</
Grid.RowDefinitions>

And finally add the controls to the grid:

  <TextBlock Grid.Row="1" Grid.Column="1"
Text="Input value:"
Style="{StaticResource FSharp}"/>

<
TextBox Grid.Row="1" Grid.Column="3"
x:Name="inputValue"
FontFamily="Verdana" FontSize="32" />

<
Button Grid.Row="2" Grid.Column="1"
Grid.ColumnSpan="3"
Content="Is it a prime?" x:Name="calculate"
HorizontalAlignment="Center" VerticalAlignment="Center"
Foreground="#FFE68484"
FontFamily="Verdana" FontSize="32"/>

<
TextBlock Grid.Row="3" Grid.Column="1"
Text="Result:"
Style="{StaticResource FSharp}"/>

<
TextBlock Grid.Row="3" Grid.Column="3"
x:Name="result"
Style="{StaticResource FSharp}" />



This is page in de designer:



Designer

Now is time to add the F# code. We add an F# Portable Library call “MathLib” to the solution.

FSharpProject


Rename PortableLibrary1 to Lib and delete the Script file.

FSharpProject2

And add the F# code to the Lib file:
module MathLib.Prime
let IsPrime n =
if n < 2L then
false
else
seq
{ 2L .. n - 1L}
|> Seq.exists(
fun x -> n % x = 0L)
|> not

This is not the most sophisticated prime check but it will do for our projects.

We have created a module we can use MathLib is the namespace, Prime is a static class and IsPrime is a static function.

The code i in line with the definition of a prime number: A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.

Now we have to create interoperability. We add a reference to the MathLib project:

AddReference

and build the solution. This will make the meta data of the MathLib project available for the  WinRTFSharpSimple project.

Next we create add a button click event:
 <Button Grid.Row="2" Grid.Column="1"
Grid.ColumnSpan="3"
Content="Is it a prime?" x:Name="calculate"
HorizontalAlignment="Center" VerticalAlignment="Center"
Foreground="#FFE68484"
FontFamily="Verdana" FontSize="32" Click="OnClick"/>

and add an handler at the code behind:

private voidOnClick(objectsender,RoutedEventArgs e)
{
    result.Text =
Prime.IsPrime(Convert.ToInt64(inputValue.Text)).ToString();
}


and add a namespace:

OnClick

Time to test the app, F5:

screenshot_01232013_200741

screenshot_01232013_200947

This looks fine.

In case we enter 756771235126757131

screenshot_01232013_201358

the app freezes and we can not interact with the app (issue 1).

In case we enter “abc” the app crashes (issue 2).

How could we solve these issues?

We can fix them at the C# site or we could fix the at F# site, both are possible. In the next post I will discuss a solution at the F# site.

Total Pageviews