In my last post we created an windows apps and discussed the F# and C#/XAML interoperability. We discovered two issue:
- Long running calculations made the UI frees.
- The improper handling of the input made the app crash.
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.
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.
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.
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:
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.
No comments:
Post a Comment