Porting a .net application to Linux/Mono/MonoDevelop

I have a small .net application that I wanted to run on Linux since it is a deamon/service sort of app. Basically is an app that peridically retrieves data from a REST service and stores it to a PostgreSQL database using LLBLGenPro 5.0 CTP2. So I created a .net 4.6.1 console application that uses HttpClient/ModernHttpClient package, NLog package for logging and System.Collections.Immutable package for immutable collecitons obviously. That was on Windows using Visual Studio 2015. After I added all the necessary code it run perfectly well on Windows.

Then I tried to open the same solution on Linux. I cloned the repository and opened it in MonoDevelop 5.10/Mono 4.2.1 (both latest). And it didn’t work out of the box. I stumbled over several issues I will describe here.

.net version

MonoDevelop doesn’t work with anything over .net 4.5 for the time being due to the MSBuild thing – at least that was the complaint.

Hence I downgraded my project to .net 4.5. No problems since I didn’t use anything .net 4.6ish.

System.Collection.Immutable

It won’t install System.Collection.Immutable package because System.Linq package (which System.Collection.Immutable depends on for some reason) won’t install unless NuGet Package Manager is 3.0 or newer. MonoDevelop uses NuGet Package Manager 2.8.7. While this is only a NuGet Package installation issue, it is annoying. First, because System.Collection.Immutable doesn’t really require System.Linq package on Mono/.net 4.5 and next becuse it isn’t smooth as it should be. Funny thing is that at NuGet web page it says that System.Collection.Immutable requires NuGet 2.8.6 or higher. I guess it should be 3.0 or higher since a package that it depends on requires it.

Hence I dropped System.Collection.Immutable package which wasn’t difficult because I wasn’t using it extensively. Hopefully MonoDevelop catches up with NuGet and that is fixed.

HttpClient/ModernHttpClient

ModernHttpClient speeds up communication since it uses native networking libraries. However it won’t work on Linux.

Dropped it since it doesn’t affect the functionallity at all.

NLog

I had configure NLog though nlog.config file. And it works on Windows perfectly. Hower when run on Linux I didn’t get any output whatsoever. Just like there was no configuration file. As a Windows guy I was a bit puzzled why. Since NLog is open source, I downloaded the code and tried debugging. Sadly MonoDevelop didn’t allow me to step into NLog code for some reason but luckily old school “Console.WriteLine” approach worked as usual. After some strategically placed Console.WriteLine calls within NLog library I found the reason, which might be apparent to a Linux guy. Bloody file name casing. I was using nlog.config and Windows doesn’t care about file name casing.

On Linux file name casing does and thus changing the name to NLog.config did the trick.

Linux specific addition

If app wants to gracefully handle SIGTERM signal (like when somebody/something tries to kill it) it might use UnixSignalWaiter NuGet package. While only at version 0.0.1 it seems to work just fine. It is also safe to use it on non-Linux systems where it does nothing (one might also check whether the feature is supported).

Conclusion

If .NET Core has proper database support (PostgreSQL in my case, but more more importantly LLBLGenPro doesn’t work due to lack of ado.net support – I don’t know about you but for me the proper ado.net stack on server is one of the most important aspects) I’d try to use it as well. But since it doesn’t, well, someday in the future I guess.

Anyway, after learning all the problems and the workarounds above I feel more confident in my Mono/Linux skills and the application compiles fine and works as expected. I also think that Xamarin/mono guys are doing really great job. Kudos.

Did I mention that I’m using Docker to run the application? I guess that’s a topic for a future post.

TwoWay binding trap on Windows Store apps

Imagine having a TextBox bound to a viewmodel’s property in a TwoWay mode. In between a converter that does possibly an asymmetric conversion – in this case the text is uppercased (it should do for this demo).

Like this:

<StackPanel>
    <StackPanel.Resources>
        <local:UppercaseConverter x:Key="cnv" />
    </StackPanel.Resources>
    <TextBox Text="{Binding Text, Mode=TwoWay, Converter={StaticResource cnv}}" Margin="0,60,0,0" />
    <TextBlock Text="{Binding Text, Mode=OneWay}" />
    <Button Content="Test" Click="Button_Click" />
</StackPanel>

Below is an additional TextBlock for feedback and a button that assigns a value to the property bound.Here is the WPF converter (Windows Store version has a slightly different method signature)

public class UppercaseConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return null;
        else
            return ((string)value).ToUpper();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }
}

and the viewmodel with a single property and INPC implementation:

public class Tubo : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private string text;
    public string Text
    {
        get
        {
            return text;
        }
        set
        {
            if (text != value)
            {
                text = value;
                OnPropertyChanged("Text");
            }
        }
    }

    protected virtual void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, 
                new  PropertyChangedEventArgs(name));
    }
}

Finally the code behind the XAML page:

public partial class MainWindow : Window
{
    private Tubo source;
    public MainWindow()
    {
        InitializeComponent();
        source = new Tubo();
        DataContext = source;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        source.Text = "Tubo";
    }
}
Everything is pretty much straightforward. The instance of Tubo is created and assigned as DataContext. On button click a value is assigned to Tubo’s Text property. Binding picks up the PropertyChanged notifications and displays the UppercaseConverter converted value in TextBox and a raw value in TextBlock.

Now the question. What will be the two values displayed in a WPF application and in a Windows Store application after pressing the Test button? Can you guess?

I’d expect TUBO (uppercased) in TextBox and tubo in TextBlock since there is no conversion applied and user didn’t change anything.

And that’s the case with the WPF application. But the surprise result comes from Windows Store application. It shows both values as uppercased. It gets even worse, this behavior isn’t consistent, more on this later.

What actually happens is that Windows Store app (who invented that name anyway) TwoWay binding does both directions on value change: it picks the modified value from viewmodel and immediately stores it back into viewmodel. So without any user intervention the uppercased value is stored in viewmodel. Nasty I’d say.

But it gets worse. This behavior is only for visible UIElements. In other words, if the TextBox isn’t visible (Collapsed) at property change time it will act like expected, just pick the value from viewmodel but it won’t write it back to viewmodel.

The combination of both might result in edge case bugs one would really not expect and might not be caught easily.

Luckily there is a workaround. The source updating has to be done manually by

  1. Setting Binding’s UpdateSourceTrigger=Explicit
  2. Implementing own logic when to update the source (this might be tricky)

Here is how one does update the source in an overriden TextBox (better to create a Behavior though).

BindingExpression be = GetBindingExpression(TextProperty);
if (be != null)
{
    be.UpdateSource();
}

NCrunch and SQLite testing problem and solution

I have some NUnit tests on .net 4.5.1 class library against PCL and both use SQLite.Net PCL, the former uses its Win32 platform.
When running from a test runner (like CodeRush Unit Test Runner) it works just fine.
But NCrunch would throw an exception when trying to create a SQLiteConnection instance:

            path = Path.GetTempFileName();
            connection = new SQLiteConnection(new SQLitePlatformWin32(), path);  // exception thrown here

SetUp : System.TypeInitializationException : The type initializer for 'SQLite.Net.Platform.Win32.SQLiteApiWin32Internal' threw an exception.
  ----> System.Exception : Failed to load native sqlite library


I've found out that this behavior is due to the missing Interop assemblies that aren't copied by NCrunch by default (x64 and x86 folder in bin\Debug folder) to optimize the unit testing process.

Hence adding these two folders to "Additional files to include" NCrunch project configuration property does the trick - that way NCrunch will include the missing assemblies.

Find more info about troubleshooting missing files when NCrunching here.

A hidden bug in Windows Store’s ComboBox

Since some time ago I’ve been using Immutable Collections as much as I could due to their immutability contract – nothing ever changes. So far so good, but today I’ve stumbled upon an odd and occasional (at least at beginning) bug with Windows Store/8.1 ComboBox bound to an ImmutableList<T> through ItemsSource property.

I was sporadically seeing crashes in application mostly when ComboBox was somehow in between changes on the page. The random crashes is really the worst type of problem one can imagine. The Exception wasn’t saying much but it put me on the right track. It said that it couldn’t cast ComboBoxItem to T (of which ImmutableList I was using) in ImmutableList<T>.IList.IndexOf(object item) method.

Luckily I’ve found a way to crash it easily – just fill more than 10 items as ItemSource, focus ComboBox and press up or down. It would crash after 5 or so changes each time. Being able to repro the problems asap and 100% reliable is a big benefit. Huge actually.

Then I’ve exprerimented with a normal List<T> instead of an immutable one and it worked without any problem. Odd, I thought.

Now, luckily Immutable Collections are open source on github as a part of corefx. I was being ready for a pull request if I could fix the bug. I was cloning the repository in no time and then tried to reference sources instead of NuGet package. There were two obstacle on my way:

  1. The version of Immutable Collections in corefx is using .net 4.5 which is not a good framework for a Windows Store app. Hence I created a blank Windows Store library and copied all sources there. That worked almost perfectly.
  2. Exceptions were using localized strings from a static class SR which I really didn’t have time to figure out where it comes from. I merely commented out these exceptions and replaced them with new Exception();

At this point the project compiled and I was ready to debug with sources. And soon it stopped in the offending method: ImmutableList<T>.IList.IndexOf(object item). The thing is that ComboBox was passing an ComboBoxItem (even though I was using items of type T) and ImmutableList<T> doesn’t care to fail softly when it gets an incompatible item type (note that IList isn’t generic). As, I discovered later, is the case with List<T>: it would return –1 when an incompatible type is passed whereas ImmutablList<T> would just crash.

 

However, I figured out that this is not a problem of ImmutableList<T> but of rather poor implementation of ComboBox in Windows Store (and perhaps of other similar types). Now, to make it worse, there are no sources for Windows Store ComboBox since it is a C++ dude and is virtually unfixable in the time I’d need the fix if I were to report the error somehow.

So the only solution for the time being is to switch to List<T> and avoid ImmutableList<T> even though it doesn’t mutate ever.

You’ve been warned!

 

Here is the repro code, just create a Windows Store app, get ImmutablCollections from NuGet and paste this xaml:

<ComboBox x:Name="combo" VerticalAlignment="Center" FontSize="70" Width="500"
           SelectedValue="{Binding ItemId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Id">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Text}" />
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

and this codebehind:

public sealed partial class MainPage : Page
    {    
        Tubo tubo;
        public MainPage()
        {
            this.InitializeComponent();
            List<Item> items = Enumerable.Range(1, 20)
                 .Select(i => new Item { Id = i, Text = i.ToString() }).ToList();
            tubo = new Tubo();
            tubo.ItemId = 5;
            DataContext = tubo;

            combo.ItemsSource = items.ToImmutableList();
        }
    }

public class Item
{
    public int Id { get; set; }
    public string Text { get; set; }
}

public class Tubo
{
    public int ItemId { get; set; }
}
Update: I've checked with Windows 10 preview and VS2015CTP and the same bug is still there. Yuck.

(Android) Emulator on Hyper-V

An apparently great news is that Microsoft has been cooking up an Android emulator. It appears that every company now feels compelled to create one. Right now we have Google’s emulator, Intel HAXM support for it, Genymotion, Xamarin Android emulator and now the Visual Studio’s one. It is getting crowded, isn’t it?

So, why I did write an apparently great news. Because the VS Android emulator, just like Windows Phone emulator, runs on top of Hyper-V. Which is not bad from the technical point of view but it is certainly not a good option on a developer machine. And that’s because turning on Hyper-V means that no other virtualization host can coexist. That’s right, forget about VMWare Workstation and Virtual Box when Hyper-V is turned on. Which makes sense on a server but on a developer machine it is sort of silly. The solution? According to Hyper-V crowd it is simple:

Just reboot with Hyper-V turned on or off, depending on your needs.

Which is … silly and really annoying. Heck, even Microsoft acknowledges this problem and it even lists it as one of the motivations beneath Visual Studio’s Emulator for Android:

Conflict with Hyper-V on Windows. Many emulators require you to disable Hyper-V or don’t work as well with Hyper-V as they do without. Using Hyper-V is part of the development setup for many developer activities, so asking you to restart your machine (multiple times a day) to toggle Hyper-V is not acceptable.

I agree that switching Hyper-V on and off is not acceptable. Bot nor is this solution. Instead of getting rid of (or modifying) Hyper-V when it comes to emulators, Microsoft decided to start creating all sort of emulators based on Hyper-V instead. Which is somehow conflicting with the awesome direction of open sourceness and multi platforms MS recently took. On the one hand they are going all nuts with open source and collaboration with other OS (amazing, btw) while on the other hand they are trying to monopolize virtualization on workstation machines. In the times when a mobile developer has to work with all sorts of different tools and software!

Other issues with the Hyper-V based emulator are that they require SLAT support (won’t run on older CPUs) and that they require Windows 8.x Pro or better. Both VMWare Workstation and Virtual Box run on “every” Windows you throw at them. Ah, and don’t forget that it will hardly support Google Play out of the box due to the Google’s silly restrictions (no emulator is allowed to ship Google Play except Google’s own).

So, the bottom line is, that yet another Android emulator is welcome, but it could be done much better. I’ll probably stick with Genymotion for the time being, since it works regardless of Hyper-V and is more feature packed that the rest.

Thinking about delayed getters on properties in C#6.0 or after that

Here is a typical scenario where one postpones property value creation until the property getter is accessed:

private SomeType something;

public SomeType Something 
{
   get
   {
     if (something == null)
     {
       something = new SomeType();
     }
     return something;
   }
}

This pattern is usually applied when property SomeType is rarely used. It doesn’t make much difference on desktop applications (unless there is a ton of these properties) but it might make some performance gains on mobile apps where performance is more critical and memory is less abundant. Of course, one could use Lazy<T> but that would create an instance of Layz<T> instead plus the instance of SomeType eventually.

Now, there is a Expression bodies on property-like function members proposition for C# 6.0 that allows getter-only properties to be implemented with an expression, i.e.:

public string Name => First + " " + Last;

However, full lambdas aren’t supported thus something field can’t be assigned and we’d end up with a new SomeType instance each time.

So, I was thinking a bit about how that could be implemented and here is my proposition for delayed getter-only property assignment:

public SomeType Something => const new SomeType();

This would cause the instance of SomeType to be created only when getter is first time accessed and after that the same instance would be used just like in the original example.

What do you think?

Finally upgraded to Windows 8.1 (from 8.0)

Since Microsoft released Windows 8.1 I’ve tried to upgrade my 8.0 to 8.1. Without success though. Every upgrade ended just a little bit before 100% with a BSOD and after some automatic retries to remedy the situation it simply rolled back to 8.0. By looking at the log file produced it was obvious there is a problem with a driver. But which one?

After some retries I gave up. Until now. The reason for my retry was that I found a dead computer (motherboard) after my vacation. I’ve replaced dead motherboard with a newer model (simply because the old one isn’t available anymore) and retried upgrading to 8.1 (thinking it might have been motherboard related). And I succeeded. The upgrade went through without problems. Hura. But.

After a while a realized that I didn’t plug in all my USB devices yet. So I started plugging them in only to create a BSOD after BSOD. By trial and error I’ve found that USB devices that act like disks are causing this problem (I have two of those). Then I went examining the crash dump. And there it was the real culprit in all its glory: iaStorF.sys aka Intel’s disk driver:

Debugging Details:
------------------


POOL_ADDRESS:  ffffe0000040f160 Nonpaged pool

FREED_POOL_TAG:  RstF

BUGCHECK_STR:  0xc2_7_RstF

CUSTOMER_CRASH_COUNT:  1

DEFAULT_BUCKET_ID:  WIN8_DRIVER_FAULT

PROCESS_NAME:  System

CURRENT_IRQL:  0

ANALYSIS_VERSION: 6.3.9600.16384 (debuggers(dbg).130821-1623) amd64fre

LAST_CONTROL_TRANSFER:  from fffff800ed2af338 to fffff800ed16a0a0

STACK_TEXT:  
ffffd000`20737018 fffff800`ed2af338 : 00000000`000000c2 00000000`00000007 00000000`00001205 00000000`04070015 : nt!KeBugCheckEx
ffffd000`20737020 fffff800`0105131e : 00000000`00000000 ffffe000`0c4ddb01 ffffe000`0b2f8010 ffffe000`01a05630 : nt!ExDeferredFreePool+0xbb8
ffffd000`207370f0 00000000`00000000 : ffffe000`0c4ddb01 ffffe000`0b2f8010 ffffe000`01a05630 ffffe000`0041a870 : iaStorF+0x131e


STACK_COMMAND:  kb

FOLLOWUP_IP: 
iaStorF+131e
fffff800`0105131e ??              ???

SYMBOL_STACK_INDEX:  2

SYMBOL_NAME:  iaStorF+131e

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: iaStorF

IMAGE_NAME:  iaStorF.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  4f7e1f6d

FAILURE_BUCKET_ID:  0xc2_7_RstF_iaStorF+131e

BUCKET_ID:  0xc2_7_RstF_iaStorF+131e

ANALYSIS_SOURCE:  KM

FAILURE_ID_HASH_STRING:  km:0xc2_7_rstf_iastorf+131e

FAILURE_ID_HASH:  {f7fa26b6-6e68-69b5-7668-84d625b41a69}

How does one fix that? Googling of course. Here is the solution from Hans-HermannKaas. It looks like Windows 8.1 changed something regarding drivers (see Herman’s explanation) and nor Intel nor Microsoft handle it when upgrading. Tough one to understand.

Basically you would want to copy iaStorF.sys from IRST driver’s package x64 folder into c:\windows\system32\drivers folder. For me – I had an outdated version there.

But because you can’t do that before upgrading you’ll have to detach all USB devices that act like disks, upgrade, fix this and only then reattach them.

There you go.

Different XAML layouts for different device orientations in Xamarin.Forms

In case you’ve been wondering how to achieve different XAML layouts for different device orientation with Xamarin.Forms (just Forms from now), here is a solution. The thing is that there is currently no support for this. There is support for different layout when it comes Phone vs Tablet (OnIdiom<T>) or when it comes to different OS (OnPlatform<T>) but the thing is that these guys are static. They do their work once and that’s it. They won’t react to changes and it makes sense, since underlying OS or device type don’t change during runtime.

So something different is need. But before I even start with the XAML there is an important part that has to be done – getting the current orientation, or better, rotation at the Portable Class Library level. It is a twofold solution.

Here is code that exists in PCL project and isn’t OS specific.

public enum Rotation
{
    Rotation0,
    Rotation90,
    Rotation180,
    Rotation270
}
public static class Orientation
{
    private static Rotation rotation;
    public static EventHandler RotationChanged;
    public static Rotation Rotation
    {
        get
        {
            return rotation;
        }
        set
        {
            if (Rotation != value)
            {
                rotation = value;
                OnRotationChanged();
            }
        }
    }

    public static bool IsLandscape
    {
        get
        {
            return Rotation == Rotation.Rotation90 
                || Rotation == Rotation.Rotation270;
        }
    }

    private static void OnRotationChanged()
    {
        if (RotationChanged != null)
            RotationChanged(null, EventArgs.Empty);
    }
}

And here is the OS specific part where you set the orientation.

Android version:

public class MainActivity : AndroidActivity
{
    protected override void OnCreate (Bundle bundle)
    {
        UpdateCurrentRotation();
        base.OnCreate (bundle);

        Xamarin.Forms.Forms.Init (this, bundle);

        SetPage (App.GetMainPage ());
    }

    public override void OnConfigurationChanged(Android.Content.Res.Configuration newConfig)
    {
        base.OnConfigurationChanged(newConfig);
        UpdateCurrentRotation();
    }

    private void UpdateCurrentRotation()
    {
        switch (WindowManager.DefaultDisplay.Rotation)
        {
            case  SurfaceOrientation.Rotation0:
                Orientation.Rotation = Rotation.Rotation0;
                break;
            case SurfaceOrientation.Rotation90:
                Orientation.Rotation = Rotation.Rotation90;
                break;
            case SurfaceOrientation.Rotation180:
                Orientation.Rotation = Rotation.Rotation180;
                break;
            case SurfaceOrientation.Rotation270:
                Orientation.Rotation = Rotation.Rotation270;
                break;
        }
    }
}

Windows Phone version (note that you have to set SupportedOrientations="PortraitOrLandscape" in your MainPage.xaml to enable rotation of the page):

public partial class MainPage : PhoneApplicationPage
{
    public MainPage()
    {
        InitializeComponent();
        UpdateRotation();
        Forms.Init();
        Content = App16.App.GetMainPage().ConvertPageToUIElement(this);
    }

    private void UpdateRotation()
    {
        if ((Orientation & PageOrientation.PortraitUp) 
== PageOrientation.PortraitUp) App16.Orientation.Rotation = Rotation.Rotation0; else if ((Orientation & PageOrientation.PortraitDown)
== PageOrientation.PortraitDown) App16.Orientation.Rotation = Rotation.Rotation180; else if ((Orientation & PageOrientation.LandscapeLeft)
== PageOrientation.LandscapeLeft) App16.Orientation.Rotation = Rotation.Rotation90; else App16.Orientation.Rotation = Rotation.Rotation270; } protected override void OnOrientationChanged
(OrientationChangedEventArgs e) { UpdateRotation(); base.OnOrientationChanged(e); } }

Sadly I have no iOS device at this time, but it should be pretty easy to support it as well.

At the beginning of the page/activity and each time orientation changes the current rotation is sent to Orientation class in PCL.

At this point we have the rotation information and event RotationChanges that notifies about changes in rotation. Now this information can be used to achieve the dynamic layout changes.

For that purpose I’ll use a Grid ContentView derived class that can be nicely used with XAML.

public class Rotational: ContentView
{
    public View Landscape { get; set; }
    public View Portrait { get; set; }
    public string LandscapeType { get; set; }
    public string PortraitType { get; set; }
    private bool isPortrait;

    protected override void OnParentSet()
    {
        base.OnParentSet();
        VisualElement view = ParentView;
        while (!(view is Page))
        {
            view = view.ParentView;
        }
        Page page = (Page)view;
        page.Disappearing += page_Disappearing;
        page.Appearing += page_Appearing;
    }

    void page_Appearing(object sender, EventArgs e)
    {
        Orientation.RotationChanged += CurrentOrientation_Changed;
        Update();
    }

    private void CurrentOrientation_Changed(object sender, EventArgs e)
    {
        Update(); 
    }

    void page_Disappearing(object sender, EventArgs e)
    {
        Orientation.RotationChanged -= CurrentOrientation_Changed;   
    }

    private void Update()
    {
        if (Content == null || Orientation.IsLandscape && isPortrait ||
            !Orientation.IsLandscape && !isPortrait)
        {
            Children.Clear();
            if (RhOrientation.IsLandscape)
{
isPortrait = false;
if (Landscape != null)
{
Content = Landscape;
}
else
{
View child = FindContentView(LandscapeType);
Content = child;
}
}
else
{
isPortrait = true;
if (Portrait != null)
{
Content = Portrait;
}
else
{
View child = FindContentView(PortraitType);
Content = child;
}
} } } private View FindContentView(string contentViewName) { var query = from t in GetType().GetTypeInfo().Assembly.DefinedTypes where t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(ContentView)) && t.Name == contentViewName select t; var contentViewTypeInfo = query.SingleOrDefault(); if (contentViewTypeInfo != null) { ContentView page = (ContentView)Activator.CreateInstance
(contentViewTypeInfo.AsType()); return view; } else return null; } }

The class is named Rotational and defines four properties: Portrait, PortraitPage, Landscape and LandscapePage. Portrait and Landscape are of type View and you can store View derived classes that would appear based on orientation. Here is an example:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                       xmlns:v="clr-namespace:App16;assembly=App16"
                       x:Class="App16.TestPage">
  <v:Rotational>
    <v:Rotational.Landscape>
      <StackLayout Orientation="Vertical">
        <Label Text="Landscape" HorizontalOptions="Center" />
      </StackLayout>
    </v:Rotational.Landscape>
    <v:Rotational.Portrait>
      <StackLayout Orientation="Vertical">
        <Label Text="Portrait" HorizontalOptions="Center" />
      </StackLayout>
    </v:Rotational.Portrait>
  </v:Rotational>
</ContentPage>

Note that namespace declaration is required (xmlns:v="clr-namespace:App16;assembly=App16"). The above definition will show a label saying Portrait or Landscape, depending on device rotation and will change dynamically. The drawbacks of this approach are that both configurations are in-memory and the page might become a bit bloated.

Hence the second pair of properties: PortraitPage and LandscapePage. These are of string type and allow to enter the page class names the content of which will be used dynamically. Here is an example:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:v="clr-namespace:App16;assembly=App16"
                       x:Class="App16.TestPage">
  <v:Rotational PortraitType="PortraitTestContent" 
LandscapeType="LandscapeTestContent" /> </ContentPage>

Additional two pages are required (PortraitTestContent.xaml and LandscapeTestContent.xaml):

<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
                       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                       x:Class="App16.PortraitTestPage">
    <Label Text="Portrait test" VerticalOptions="Center" 
HorizontalOptions="Center" /> </ContentView> ... <ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App16.LandscapeTestPage"> <Label Text="Landscape Test" VerticalOptions="Center"
HorizontalOptions="Center" /> </ContentView>

The pages are found using reflection and based on their names (no namespace is used).

This method is more memory efficient since it loads required content on demand and discards it afterwards. On the other side it is slower due to the loading of the page.

So, here you have it. What do you think? Is there a better way?

The sample is attached.

Rotational.zip (77.2KB)

Update 1: Instead of dynamically loading ContentPage and then using its content, ContentView should be used (it is XAML supported). That'd be a change in FindPageElement method to FindContentView.
Update 2: Changed base type for Rotational from Grid to ContentView.

Note: sample hasn't been updated from original version.

An async problem

Imagine you have an asynchronous cancellable method like this:

CancellationTokenSource cts;

async Task DoSomethingAsync()
{
    if (cts != null)
        cts.Cancel();
    cts = new CancellationTokenSource();
    try
    {
        await AnAsyncMethodAsync(cts.Token);
    }
    finally
    {
        cts = null;
    }
}

And you trigger it here and there. The idea is that if it is already running when triggered (cts != null) it should send cancellation signal through its token.

Now, can you spot a possible problem that can occur?

The answer: DoSomething starts and is awaiting, another call is issued, original call is cancelled, second call is awaiting, original call advances to finally block (cts is set to null). Third call chimes in but this time cts is null (because original call set cts to null) even though second call is awaiting and thus second call is *not* cancelled, third call is awaiting and both second and third will finish.

There you go.

An alpha version of memory profiler for Xamarin Android

Memory profiling is one of the pillars of a good application. Even more important is on mobile devices since memory is usually scarce there. But sadly, there is no memory profiler for Xamarin Android development. Actually there is some raw support but lacks UI and friendliness. Hence I’ve built my own memory profiler.

This is an alpha quality version.

How it works

Since version 4.14 Xamarin has a (not) very visible support for memory profiling. But even with this support it isn’t easy to profile. With each garbage collection a log file is written on the device containing all the relevant data in a text format. Note that once you turn profiling on with

adb shell setprop debug.mono.profile log:heapshot

This setting is global and it works on all Xamarin apps on the device. Remember to turn it off afterwards if you don’t need it anymore to avoid, I guess, a huge performance hit.

There are two problems with the existing support here:

  • hard to trigger a garbage collection manually
  • hard to analyze data

My solution tackles both problems. The solution is divided into two parts.

Server side

The library available through NuGet does two things:

  • broadcasts its presence through UDP
  • allows triggering garbage collection from client

The library supports API Level 4 (Xamarin v1.6) and above.

Here is the NuGet package URL. You can also install it using this Package Manager Console command:

Install-Package RhMemProfiler.Server –Pre

The package is marked as prerelease and it won’t appear in NuGet Package manager if it isn’t set for Include Prerelease.

Once package has been added go ahead and create a global variable of type RhMemProfiler.Server.Beacon and initialize it with a friendly name and package name, like:

RhMemProfiler.Server.Beacon beacon;
….
beacon.Start("your friendly name", PackageName);

PackageName is the name of your package and it is ContextWrapper’s property.

Client side

This is a Windows application distributed through ClickOnce. After installation you’ll be prompted to open the firewall for the application. This is required since it, well, uses UDP and TCP to communicate with the server side.

profilerPrivate networks access is enough unless your mobile device is running on public network.

Once that is done you’ll be presented with a main window:

profiler

If your application on mobile device/emulator is running then you’ll see at least one option (one per IP on the device) in the combo box left of Connect button. That list contains friendly name (used when initializing on server) and its IP address. Pick any of them (IP doesn’t matter at this time). Hit Connect button.

If connection is successful you’ll see Conncted text in bottom left corner. If this is the first time you are connecting and/or memory profiling isn’t enabled yet on the device then you’ll be presented the Enable Profiling button, like:

enableprof

Enable profiling, restart mobile device application, disconnect, connect again and your are good to start memory profiling:

enableprof

Once there were at least two garbage collections and a snapshot has been taken afterwards you are able to compare them by selecting start and end version.

Collect Garbage … forces garbage collection on the mobile device
Snapshot … collects memory profiling log file from the device
Disable profiling … disables profiling on the device (profiling is per device, not per application – it affects all Xamarin apps on that device)
Only with source … shows only types from your package
Group panel … lets you group columns
Start and End … memory profile versions to compare to

Test

Imagine I have a class

public class MemLeak
{
    public string Value;
}

and a list of these somewhere defined. If I do a garbage collection before, when list is empty, and after one instance of MemLeak has been added I’ll see something like this when comparing before and after:

leak

It is pretty much obvious that the count of MemLeak instances increased by 1 and there are total of two instances of it around (actually I created one before that’s why there are two of them).

Memory profiling strategy

Memory profiling works by comparing state before and after. Usually a garbage collection is taken before some action and after that action. If the number of some instance increased without a valid reason it means that the application is leaking memory. Professional memory profilers help you even pinpointing the source of the leaks, however in our case, Xamarin doesn’t have that data available through this strategy.

Known limitations

  • ADB has to be in the path.
  • Only one device or emulator can be connected to the computer at the same time (the combo lets you pick the application but not the IP)

Final words

This is an alpha release, so be gentle with it and do not complain if your computer explodes because of it. It is something I wanted to release even at this stage for you to play with. It is actually pretty functional. So, feedback is appreciated and so are questions but I don’t guarantee anything, the development is done in my spare time (like that there is any Smile) for now. Hope you’ll find it useful.