Random number with alias method in C#

Example about generating random number using the alias method in C#

    public static class RandomExtensions
        public static int GetAlias(this Random rnd, IEnumerable probs)
            int random = rnd.Next(probs.Sum());
            int sum = 0;
            int idx = 0;
            foreach (var p in probs)
                sum += p;
                if (sum >= random)

            return idx;
        } // GetAlias

We pass the method a list of int containing the probability we want for that index.

Test program

    class Program
        class Animal 
            public Animal(string name) {
                Name = name;
            public string Name { get; set; }
            public int Count { get; set; }

        static void Main(string[] args)
            List values = new List
                new Animal("Cat"),
                new Animal("Dog"),
                new Animal("Sheep"),
                new Animal("Cow"),
                new Animal("Turtle"),

            int[] probs = new int[] { 10, 50, 10, 10, 20 };
            Random rnd = new Random();
            for (int i=0; i < 100; i++) {
                int number = rnd.GetAlias(probs);

            foreach (var a in values) {
                Console.WriteLine($"{string.Format("{0,-10}", a.Name)}: {string.Format("{0,2}", a.Count)}");

Test program output

Cat       :  6
Dog       : 49
Sheep     : 12
Cow       : 11
Turtle    : 22

Avalonia UI Framework localization

So you want to localize your application developed using the Avalonia UI Framework? Let’s see how it can be done.

Some informations are taken from this bug report.

To localize an application we must be able to

  • Localize strings directly in the XAML
  • Get access to the localization strings in the code

To translate strings in the XAML we can use a custom MarkupExtension and bindings

    public class LocalizeExtension : MarkupExtension
        public LocalizeExtension(string key)
            this.Key = key;

        public string Key { get; set; }

        public string Context { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
            var keyToUse = Key;
            if (!string.IsNullOrWhiteSpace(Context))
                keyToUse = $"{Context}/{Key}";

            var binding = new ReflectionBindingExtension($"[{keyToUse}]")
                Mode = BindingMode.OneWay,
                Source = Localizer.Instance,

            return binding.ProvideValue(serviceProvider);

Note that in addition to the string key there’s also a context, used to have different translations for the same string in different contexts.

This extension can be used in XAML:

<Window xmlns="https://github.com/avaloniaui"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        Width="500" Height="350"

  <StackPanel Orientation="Vertical" Margin="15">
    <Label Content="{i18n:Localize Language}" />
    <ComboBox SelectedIndex="0" SelectionChanged="OnLanguageChanged">

    <TextBlock FontSize="21" Text="{i18n:Localize HelloWorld}"/>
    <TextBlock FontSize="21" Text="{i18n:Localize HelloWorld, Context=Second}"/>
    <TextBlock FontSize="21" Text="{i18n:Localize MissingTranslation}"/>

We need to define the namespace first


then we can bind strings using our MarkupExtension

<TextBlock FontSize="21" Text="{i18n:Localize HelloWorld}"/>

Now we need a way to translate the strings to the desired language. An easy way is to use JSON files containing the context/key with the corresponding translated text. We can embed the JSON files using assets

Missing strings are displayed as the language code followed by a semicolon and the string key.

public class Localizer : INotifyPropertyChanged
        private const string IndexerName = "Item";
        private const string IndexerArrayName = "Item[]";
        private Dictionary<string, string> m_Strings = null;

        public Localizer()


        public bool LoadLanguage(string language)
            Language = language;
            var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();

            Uri uri = new Uri($"avares://AvaloniaLocalizationExample/Assets/i18n/{language}.json");
            if (assets.Exists(uri)) {
                using (StreamReader sr = new StreamReader(assets.Open(uri), Encoding.UTF8)) {
                    m_Strings = JsonConvert.DeserializeObject<Dictionary<string, string>>(sr.ReadToEnd());

                return true;
            return false;
        } // LoadLanguage

        public string Language { get; private set; }

        public string this[string key]
                string res;
                if (m_Strings != null && m_Strings.TryGetValue(key, out res))
                    return res.Replace("\n", "\n");

                return $"{Language}:{key}";

        public static Localizer Instance { get; set; } = new Localizer();
        public event PropertyChangedEventHandler PropertyChanged;

        public void Invalidate()
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerName));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(IndexerArrayName));

Since we are using bindings and INotifyPropertyChanged the translated text is applied as soon as we load a new language.

To access to the translated strings in the code use the static Localizer using the string key


You can download the sample project here (Avalonia 0.10)

AvaloniaLocalizationExample.zip (31 downloads)

Enable/disable CPU turbo boost from command line

Intel’s turbo boost can be enabled and disabled in Windows using the command line.

First we need to check the active profile.

Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c  (High performance)

By default Windows does not display the turbo boost setting via the powercfg utility. To enable it use the command:

powercfg.exe -attributes SUB_PROCESSOR be337238-0d82-4146-a960-4f3749d470c7 -ATTRIB_HIDE

Using the current profile’s GUID 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c we can check if turbo boost is enabled or not.

powercfg.exe /QUERY 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 54533251-82be-4824-96c1-47b60b740d00 be337238-0d82-4146-a960-4f3749d470c7
Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c  (High performance)
  Subgroup GUID: 54533251-82be-4824-96c1-47b60b740d00  (Processor power management)
    Power Setting GUID: be337238-0d82-4146-a960-4f3749d470c7  (Processor performance boost mode)
      Possible Setting Index: 000
      Possible Setting Friendly Name: Disabled
      Possible Setting Index: 001
      Possible Setting Friendly Name: Enabled
      Possible Setting Index: 002
      Possible Setting Friendly Name: Aggressive
      Possible Setting Index: 003
      Possible Setting Friendly Name: Efficient Enabled
      Possible Setting Index: 004
      Possible Setting Friendly Name: Efficient Aggressive
      Possible Setting Index: 005
      Possible Setting Friendly Name: Aggressive At Guaranteed
      Possible Setting Index: 006
      Possible Setting Friendly Name: Efficient Aggressive At Guaranteed
    Current AC Power Setting Index: 0x00000000
    Current DC Power Setting Index: 0x00000000

The output of the command shows that turbo boost is disabled using AC and using DC:

Current AC Power Setting Index: 0x00000000 
Current DC Power Setting Index: 0x00000000

To enable turbo boost in AC:

powercfg.exe /SETACVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 54533251-82be-4824-96c1-47b60b740d00 be337238-0d82-4146-a960-4f3749d470c7 003

To enable turbo boost in DC:

powercfg.exe /SETDCVALUEINDEX 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 54533251-82be-4824-96c1-47b60b740d00 be337238-0d82-4146-a960-4f3749d470c7 003

The last argument is the index of the turbo boost mode to enable (003 is “Efficient enabled”).

To apply the changes use the command

powercfg.exe -S SCHEME_CURRENT

How to read huge Excel file using C#

Reading a Excel file is easy using the SpreadsheetDocument and SheetData classes but this method uses a lot of memory if the Excel file is big.
This is due to the fact that to get the sheet data the framework loads the entire file into memory.

To read huge files it is better to use the OpenXmlReader.

Here’s an example usage of the OpenXmlReader (it also consider the SharedString)

public static IEnumerable> ReadData(string fileName)
    using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, false)) {
        WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
        WorksheetPart worksheetPart = workbookPart.WorksheetParts.FirstOrDefault();
        if (workbookPart != null) {
            using (OpenXmlReader oxr = OpenXmlReader.Create(worksheetPart)) {
                IEnumerable sharedStrings = workbookPart.SharedStringTablePart.SharedStringTable.Elements();
                while (oxr.Read()) {
                    if (oxr.ElementType == typeof(Row)) {

                        List rowData = new List();
                        do {
                            if (oxr.ElementType == typeof(Cell)) {
                                Cell c = (Cell)oxr.LoadCurrentElement();
                                string cellValue;
                                if (c.DataType != null && c.DataType == CellValues.SharedString) {
                                    SharedStringItem ssi = sharedStrings.ElementAt(int.Parse(c.CellValue.InnerText));
                                    cellValue = ssi.Text.Text;
                                } else {
                                    cellValue = c.CellValue.InnerText;

                        } while (oxr.ReadNextSibling());

                        yield return rowData;
} // GetData

To loop the Excel’s rows

foreach (List rowData in ReadData(fileName)) {

The OpenXmlReader uses less memory, but it is slow.
For faster reading you can use the ExcelDataReader, it is available also as a NuGet package.

How to use the BASS audio library in UWP development

The BASS audio library is a solid library to decode and play many audio formats, supports gapless playback (using the mixer, not used in this example) and equalizer (not used in this example).

The library is available also for Windows Store development.

To reference the BASS audio library in your UWP project remember to add conditional references based on platform in the csproj file

<ItemGroup Condition="'$(Platform)' == 'x86'">
  <Content Include="$(SolutionDir)bass\Windows 10\x86\bass.dll">
<ItemGroup Condition="'$(Platform)' == 'x64'">
  <Content Include="$(SolutionDir)bass\Windows 10\x64\bass.dll">
<ItemGroup Condition="'$(Platform)' == 'ARM'">
  <Content Include="$(SolutionDir)bass\Windows 10\arm\bass.dll">

Let’s see how we can use the library in a background audio player.

First we need the background task. Here we initialize the BASS audio library, and free it when the task ends. Since we are going to use BASS only to decode the audio we can use the “no sound” device.

using System;
using Un4seen.Bass;
using Windows.ApplicationModel.Background;
using Windows.Foundation.Collections;
using Windows.Media.Playback;

namespace BackgroundPlayer
  public sealed class Player : IBackgroundTask
    BackgroundTaskDeferral m_Deferral;
    BassMediaSource m_MediaSourceAdapter = null;

    public void Run(IBackgroundTaskInstance taskInstance)
      m_Deferral = taskInstance.GetDeferral();
      taskInstance.Canceled += TaskInstance_Canceled;
      taskInstance.Task.Completed += TaskInstance_Completed;

      BassNet.Registration("Your email", "Your registration key");
      if (!Bass.BASS_Init(0, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero)) {
        BASSError err = Bass.BASS_ErrorGetCode();

      BackgroundMediaPlayer.MessageReceivedFromForeground += OnMessageReceived;

    private void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)

    void TaskInstance_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)

Now we need to play the file when the foreground app asks for it. Communication between the foreground app and the background task is made through messages.

When the background task receives a “file” request message it opens the file using BASS (we’ll see later how) and sets the media source of the bacgkround media player.

private async void OnMessageReceived(object sender, MediaPlayerDataReceivedEventArgs args)
  ValueSet msg = args.Data;

  if (msg.ContainsKey("file")) {
    string audioFile = msg["file"] as string;
    if (!string.IsNullOrEmpty(audioFile)) {
      m_MediaSourceAdapter = await BassMediaSource.CreateAsync(audioFile);
      BackgroundMediaPlayer.Current.Source = MediaSource.CreateFromIMediaSource(m_MediaSourceAdapter.GetMediaSource());

The BassMediaSource class implements IMediaSource and is the one responsible of opening and playing the file.

The code is quite simple: we need to create the decode stream for the BASS audio library and listen to the MediaSource events (Closed, Starting, SampleRequested).

public async Task InitializeAsync()
  StorageFile sFile = await StorageFile.GetFileFromPathAsync(m_FilePath);
  BasicProperties prop = await sFile.GetBasicPropertiesAsync();
  m_FileSize = prop.Size;

  m_BassHandle = Bass.BASS_StreamCreateFile(m_FilePath, 0, (long)m_FileSize, BASSFlag.BASS_STREAM_DECODE);
  if (m_BassHandle == 0) {
    BASSError err = Bass.BASS_ErrorGetCode();
    System.Diagnostics.Debug.WriteLine("InitializeAsync error {0}", err);

  BASS_CHANNELINFO cInfo = Bass.BASS_ChannelGetInfo(m_BassHandle);
  if (cInfo == null) {
    BASSError err = Bass.BASS_ErrorGetCode();
    System.Diagnostics.Debug.WriteLine("InitializeAsync error {0}", err);
  long len = Bass.BASS_ChannelGetLength(m_BassHandle, BASSMode.BASS_POS_BYTES);
  double secs = Bass.BASS_ChannelBytes2Seconds(m_BassHandle, len);
  uint bits = 16;
  if (cInfo.Is32bit)
    bits = 32;
  else if (cInfo.Is8bit)
    bits = 8;

  AudioEncodingProperties pcmprops = AudioEncodingProperties.CreatePcm((uint)cInfo.freq, (uint)cInfo.chans, bits);
  m_MediaStreamSource = new MediaStreamSource(new AudioStreamDescriptor(pcmprops));
  m_MediaStreamSource.CanSeek = true;
  m_MediaStreamSource.BufferTime = TimeSpan.Zero;
  m_MediaStreamSource.Duration = TimeSpan.FromSeconds(secs);
  m_MediaStreamSource.Closed += mss_Closed;
  m_MediaStreamSource.Starting += mss_Starting;
  m_MediaStreamSource.SampleRequested += mss_SampleRequested;
} // InitializeAsync

The SampleRequested event occurs when then audio player needs a decoded sample to play. Here we just need to decode the requested data and return it to the player.

void mss_SampleRequested(MediaStreamSource sender, MediaStreamSourceSampleRequestedEventArgs args)
  var deferral = args.Request.GetDeferral();

  try {
    byte[] buffer = new byte[4096];
    int decoded = Bass.BASS_ChannelGetData(m_BassHandle, buffer, buffer.Length);
    if (decoded == -1) {
      BASSError err = Bass.BASS_ErrorGetCode();
      System.Diagnostics.Debug.WriteLine("mss_SampleRequested error {0}", err);
    } else {
      double secs = Bass.BASS_ChannelBytes2Seconds(m_BassHandle, decoded);

      MediaStreamSample sample = MediaStreamSample.CreateFromBuffer(buffer.AsBuffer(), TimeSpan.FromSeconds(m_SecondsPosition));
      sample.Duration = TimeSpan.FromSeconds(secs);
      m_SecondsPosition += sample.Duration.TotalSeconds;
      args.Request.Sample = sample;
  } catch { }
} // mss_SampleRequested

The application lets you select a file from your music library (files outside of your music library won’t work because the application does not have access to external folders).

Here’s the full source code of the test program (remember to set your BASS registration info)

Download source code

Have fun! 😉