Q:

Quickest way to generate an unknown amount of buttons at runtime without freezing the app?

I have a WPF application written in C#. On this I have a canvas element that i would like to create a grid of buttons on, every button will be of equal width and height and positioned side by side with no spacing.
I have tried a few things, the first thing i did was nested for loops on the constructor method. This locked up the window until it was done generating the buttons, but it was relatively quick for a 100x100 grid. I then moved it to Loaded event, which allowed the window to open immediately but still locked it up until all buttons were generated.
I then attempted a timer and the Dispatcher on the UI elements i wanted to change, but this proved to be very slow.
Here is my current attempt at this, it does work and it doesnt lock up the UI window, but it is still abhorrently slow.
public partial class MainWindow : Window
{
    private DispatcherTimer timer;
    private int width = 100;
    private int height = 100;
    private int toDo = 0;
    private int done = 0;
    private int x = 0;
    private int y = 0;

    public MainWindow()
    {
        toDo = width * height;
        InitializeComponent();
        Loaded += MainWindow_Loaded;
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {

        //TimerCallback callback = generateButtons;
        //timer = new Timer(callback, null, 1, 1);
        DispatcherTimer timer = new DispatcherTimer();
        timer.Interval = new TimeSpan(0,0,0,0,1);
        timer.Tick += generateButtons;
        timer.IsEnabled = true;
    }

    public void generateButtons(object sender, EventArgs e)
    {
        if(x < width){
            if(y < height)
            {
                Button tileButton = new Button();
                tileButton.Content = "Blank";
                tileButton.Name = "Tile_" + x.ToString() + "_" + y.ToString();
                tileButton.Width = 15;
                tileButton.Height = 15;
                Canvas.SetLeft(tileButton, x*15);
                Canvas.SetTop(tileButton, y*15);
                this.world.Children.Add(tileButton);
                done++;
            }
            x++;
        }
        else
        {
            x = 0;
            y++;
        }
        this.progress.Value = ((float)done / (float)toDo)*100;
    }
}

Is there a quicker way of doing what I am doing?
Thinking about it is a write this, would it be quicker to create a Canvas element in code, populate that with buttons and then append the whole thing to the main windows grid? I have no idea where to start on doing this though, or wether it will infact improve performace.
Bear in mind this is for a proof of concept (therefore minimum viable product) application, it does not need to be an elegant solution, it just needs to be fast.

A:

In the code below I've illustrated how it can be done with an asynchronous approach that allows the window to stay responsive while the speed doesn't drasticly decrease as with the results of DispatchTimer.
It's been tested and works as expected:
public partial class MainWindow : Window
{
    private int width;
    private int height;
    private int toDo = 0;
    private int done = 0;
    private int x = 0;
    private int y = 0;

    public MainWindow()
    {
        InitializeComponent();
    }

    // Assigned to the canvas' "Loaded" attribute.
    private async void World_OnLoaded(object sender, RoutedEventArgs e)
    {
        width = (int)this.world.ActualWidth;
        height = (int)this.world.ActualHeight;
        toDo = width * height;
        // awaits a newly started Thread with the method StartLoopAsync
        await Task.Factory.StartNew(() => StartLoopAsync());
    }

    // Iterates the canvas width and height based on the hardcoded "15" values.
    private async Task StartLoopAsync()
    {
        for (int i = y; i < height; i += 15)
        {
            // Use Dispatcher BeginInvoke, as we are updating the UI elements from a different thread
            // other than the main thread.
            for (int j = x; j < width; j += 15)
            {
                await Dispatcher.BeginInvoke(new Action(() => GenerateButton(i, j)));
            }
        }
    }

    // Generates the button.
    private void GenerateButton(int i, int j)
    {
        Button tileButton = new Button();
        tileButton.Content = "Blank";
        tileButton.Name = "Tile_" + x.ToString() + "_" + y.ToString();
        tileButton.Width = 15;
        tileButton.Height = 15;
        Canvas.SetLeft(tileButton, j);
        Canvas.SetTop(tileButton, i);
        this.world.Children.Add(tileButton);
        //this.progress.Value = ((float)done / (float)toDo) * 100;
    }
}

Changes from your own project:

The code that was executed in Loaded, has been moved to Canvas' Loaded method.
The weight and height definitions are being set in the Canvas' Loaded method
A new thread is being assigned to the loop that iterates all the buttoncreations
Dispatcher.BeginInvoke() is used to alter UI elements in the Main Thread.

