JavaScript and different ***Script

Today I’ll just share my opinion so, no useful information bellow 🙂

There are a lot of discussions around TypeScript, CoffeeScript and other languages translated to JS. Let me add several words to this “holly war”:) I was codding for a couple of months with TypeScript. It was complex UI with Knockout.js and Durandal. Yesterday I switched to pure JavaScript task. I have to help on other our project and I have to write very simple JS code, with just several functions and some calculations.
Just imagine! My performance with JavaScript is at least twice lower than with TypeScript.
Why?
Because “continuous refactoring”, one of key principles to get good code quality, not just good looking code but stable code, is very problematic with JS. You have to check everything (variable names, functions, scopes, etc.) when you changed something in existing code.
My opinion is that Human was not designed to handle so stupid tasks 🙂 Let machines do their work use languages with checks on compilation. And use smart IDE of course 😉
Be Human…

Template project for Node.js with Express

Overview

If you are building node.js applications you may need some template project to start quickly and do not perform simple configuration every time. This configuration may contain access to MongoDB, security infrastructure and so on. My colleague Anton Dimkov has committed his template on Github. Also the template can be installed with npm.

Features

  • Configured simple routes for express
  • Integrated MongoDB access with mongoose
  • Integrated security with password hashing based on bcrypt-nodejs
  • Login page
  • Session management with express-session
  • Logging with winston
  • Integrated Angular and simple SPA front-end structure
  • Bootstrap styles integrated

Installation and configuration

  1. Install Node.js according to instructions at https://nodejs.org/
  2. Install and run MongoDB according instructions at http://www.mongodb.org
  3. Download code from git hub
  4. Install all required modules by runing npm install in terminal
  5. Run application with node www/bin
  6. Open http://localhost:9090/ in web-browser

Try it it’s simple way to start using Node.JS correctly or to start a project.

WPF vs. GDI+

The problem

In one of our projects in Tesseris Pro we need to draw huge table of results of some physical experiment. The table can be 100×100 and can be 1000×1000. The application is usual Windows desktop application built with WPF. And as usual we’ve tried to use some 3rd party grid. And as you can imagine, we’ve got unacceptable performance even with visualization. The most problematic thing is that user needs to zoom-out the table to see every cell as single pixel in this case visualization gives us nothing.

Solution #1

One of the first idea was to create our own control derived from FrameworkElement or UIElement and implement drawing of the table inside overridden OnRender method. As we expected this should give us maximum performance. And keeping in mind that WPF is based on DirectX and we will get performance as in 3D games I’ve started implementation of proof of concept with following OnRender:

protected override void OnRender(DrawingContext dc)
{
    Debug.WriteLine("OnRender...");

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < columns; j++)
        {
            int x = width * i;
            int y = height * j;

            // Draw cell rect
            dc.DrawRectangle(
                      Brushes.Green, 
                      pen, 
                      new Rect(x, y, width, height));

            // Draw some text in cell
            dc.DrawText(
                new FormattedText(string.Format("{0},{1}", i, j),
                    CultureInfo.InvariantCulture,
                    FlowDirection.LeftToRight,
                    typeface,
                    10,
                    Brushes.Black),
                new Point(x, y));
        }
    }

    Debug.WriteLine("OnRender finish");
}

But performance was still unacceptable even for table of 100×100 cells. UI was refreshed in about 10 seconds. And when I measured time elapsed by OnRender I have got strange result 800ms. UI stuck for 10 seconds but OnRender takes only 800ms. I’ve got this results because WPF never draw everything immediately inside OnRender. With dc.Draw*** you just told infrastructure to draw something. Than WPF draws all required things in some other moment. So real drawing of 100×100 table requires about 10 seconds.

Solution #2

After fail with first solution I’ve tried to get DirectDraw surface and draw everything by myself. And it is not so easy with WPF. I have not found any built functionality for this. In blogs I found that the only way to use DirectDraw is to call it through COM interop. Some nightmare for as for me!
After that I’ve decided to check GDI+ (System.Drawing namespace) and try to draw the table with System.Drawing.Bitmap and than just draw bitmap with WPF:

protected override void OnRender(DrawingContext dc)
{
    Debug.WriteLine("OnRender...");
    using (var bmp = new System.Drawing.Bitmap(
                           columns * width, 
                           rows * height))
    {
        using (var g = System.Drawing.Graphics.FromImage(bmp))
        {
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    int x = width * i;
                    int y = height * j;

                    g.FillRectangle(
                                 System.Drawing.Brushes.Green, 
                                 x, 
                                 y, 
                                 width, 
                                 height);

                    g.DrawRectangle(
                                System.Drawing.Pens.DarkGray, 
                                x, 
                                y, 
                                width, 
                                height);

                    g.DrawString(
                                string.Format("{0},{1}", i, j), 
                                font, 
                                System.Drawing.Brushes.Black, 
                                new System.Drawing.PointF(x, y));
                }
            }
        }

        // Create Image from bitmap and draw it
        var options = BitmapSizeOptions.FromEmptyOptions();
        var img = Imaging.CreateBitmapSourceFromHBitmap(
                                    bmp.GetHbitmap(), 
                                    IntPtr.Zero, 
                                    Int32Rect.Empty, 
                                    options);

        dc.DrawImage(img, new Rect(0, 0, bmp.Width, bmp.Height));
    }
    Debug.WriteLine("OnRender finish");
}

When I started the app I decided that something is going wrong. UI was refreshed in less then one second. More that 10 times faster that with WPF drawing!

Conclusion

WPF gives us complex layout and device independence and other sweet things. But old GDI+ sometimes give much more – performance and simplicity!

Explicit call to RequireJS in TypeScript

I’m working on mobile application with Apache Cordova (http://cordova.apache.org) technology. And one of the tasks was to load JSON localization file from content folder. First idea and actually most correct (as for me) is to load file with RequireJS text plugin (https://github.com/requirejs/text).
Plugin allows to load text file in the same way as usual modules and do not evaluate content, but return it as a sting. So you just specify something like following.

require(["some/module", "text!some/module.html"],
    function(module, html, css) {
        //the html variable will be the text
        //of the some/module.html file
    }
); 

When using TypeScript we can write

import html = require("text!some/module.html");

document.body.innerHTML = html;

And this will give us following JS code of the module (In case of AMD mode in compiler)

define(["require", "exports", "text!some/module.html"], 
       function (require, exports, html) {
            document.body.innerHTML = html;
       });

Unfortunately it’s not enough in case of localization, because we have to load specific html file for specific locale (text!/locale/en/module.html). And we have to select the path dynamically depending on selected locale. In JS we can write following.

define(["require", "exports","someService"], 
       function (require, exports, someService) {
            var locale = someService.getLocale();
            require(["text!/" + locale + "/en/module.html"], 
                    function(html){
                           document.body.innerHTML = html;
                    });
       });

First it was not absolutely clear for me how to do in TypeScript. There is no explicit import of RequireJS in typescript and require is a keyword used as part of module declaration. I’ve tried to find some description for my case, but without any success. Fortunately solution is much simpler that I thought:
1. You should add requre.d.ts typing to your project (or to compiler command line)
2. Than just write following TypeScript

    var locale = someService.getLocale();
    require(["text!/" + locale + "/en/module.html"], 
            html => document.body.innerHTML = html);

And this will give exactly the same code as in JS sample above. And you can ignore editor warning about keyword require, just compile the project and you will get no errors. Please note that I’ve tested this with TypeScript 1.4 compiler and with MS Visual Studio 2013. And don’t forget to use array of string as first argument of require, but not string as in another require syntax.

If you have any other idea how to make it working please add comments.

Fornt-end with Knockout.js, require.js and TypeScript

Let’s talk about how to correctly organize front-end with Knockout.js require.js and TypeScript.

The problem

If we will read TypeScript handbook we will find a lot information about how to load modules with AMD and require.js, and everywhere in samples we will find something like this

    import module=require('./module');

But in real application we always have some folder structure to keep the files organized, we are using different package managers and so on, thus in most cases import should look like

    import ko=require('./node_modules/knockout/build/output/knockout-latest')

Unfortunately for some unknown reason this is not working with TypeScript, at least with versions 1.3 and 1.4. Really, why current folder path is working but more complex path is not? We have to deal somehow with this.

An the only way is to use import ko=require(knockout) instead of full path to knockout.

In this post I will describe the way how to build HTML application with MS VisualStudio and I will use node package manger to load all the libraries, but the same idea will work for nuget or any other package managed and IDE.

Application structure

  • node_modules
    • knockout
      • build
        • output
          • knockout-latest.js
    • requirejs
      • require.js
    • moment
      • moment.js
  • typings
    • knockout
      • knockout.d.ts
    • moment
      • moment.d.ts
  • config.js
  • application.ts
  • mainViewmodel.ts
  • bindings.ts
  • index.html

Require.js enabled JavaScript (or TypeScript) application should start with single “ tag in html. In our case it looks like:

    <script data-main='config.js' src='node_modules/requirejs/require.js'></script>

This config.js is the only JavaScript file, all other logic is done in TypeScript. May be there is some way to write it on TypeScript, but I’m not sure that it makes any sense, because you have to do JS specific low level things here. The config.js looks like following:

    require.config({
        baseUrl: "",
        paths: {
            knockout: "./node_modules/knockout/build/output/knockout-latest",
            moment: "./node_modules/moment/moment"
        }
    });

    define(["require", "exports", 'application'], function (require, exports, app) {
        app.Application.instance = new app.Application();
    });

First of all in this file we are configuring require.js to make it understand where to search for libraries. We will load our index.html from file system and of course in real app you should not use folder structure but think about URLs. Please note that you should not specify file extension.

Now require.js will understand how to load knockout. But this will tell nothing our TypeScript compiler and compiler will report errors about undefined module.

To fix this problem with compiler simply add corresponding typings to the project. Now TypeScript will build everything without errors. Please note that in this case TypeScript will not verify correctness of path to modules because it can’t determine the real URL structure of the application. That may be the reason why complex path is not working in import.

Note: don’t forget to switch TypeScript module type to AMD (Asynchronous Module Definition). This will conflict with node.js and next time I will explain how to deal with node.js and AMD.

Application startup

Our application entry point (after config.js) is application.ts file with following content:

    import vm = require('mainViewModel');
    import ko = require('knockout');
    import bindings = require('bindings');

    export class Application{
        public static instance: Application;

        constructor(){
            bindings.register();
            ko.applyBindings(new vm.mainViewModel());
        }
    }

Here we load module(s) (as dependency) with all custom bindings, create main view model and apply it to whole page.

Note that we don’t need to specify path to bindings and mainViewModel in config.js because they are located at the same directory. You can use more complex structure and everything will work with TypeScript just don’t forget to explain require.js how to find all your modules.

Custom bindings

Custom binding are wrapped in single module and can be loaded as any other module. Binding handlers will be registered with bindings.register() call. This can be done with following content of bindings.ts:

    import ko = require("knockout")
    import moment = require("moment")

    export function register(): void {

        ko.expressionRewriting["_twoWayBindings"].datevalue = true;

        var formatValue = function (value, format) {
            format = ko.unwrap(format);
            if (format == null) {
                format = "DD.MM.YYYY";
            }
            return moment(ko.unwrap(value).toString()).format(format);
        }

        ko.bindingHandlers["datevalue"] = {
            init: function (element: HTMLInputElement, valueAccessor, allBindings, viewModel) {
                element.value = formatValue(valueAccessor(), allBindings.get("dateFormat"));

                element.addEventListener("change", function (event) {
                    var dateValue: any
                        = moment(element.value, ko.unwrap(allBindings.get("dateFormat")))
                            .format("YYYY-MM-DD") + "T00:00:00";

                    if (ko.unwrap(valueAccessor()) instanceof Date) {
                        dateValue = new Date(dateValue);
                    }

                    if (ko.isObservable(valueAccessor())) {
                        valueAccessor()(dateValue);
                    }
                    else {
                        allBindings()._ko_property_writers.datevalue(dateValue);
                    }
                });
            },
            update: function (element: HTMLInputElement, valueAccessor, allBindings) {
                element.value = formatValue(valueAccessor(), allBindings.get("dateFormat"));
            }
        }
    }

Here we create very useful datevalue binding, which allows to edit and display dates as string in specific format. This binding is able to work with observables and flat values and store date in JSON compatible format or Date, depending on initial value of bound property. This binding contains some knockout and TypeScript tricks like ko.expressionRewriting["_twoWayBindings"].datevalue = true and allBindings()._ko_property_writers.datevalue(dateValue) but let’s talk in next blog posts about these tricks.

ViewModel

Nothing special just usual view model organized as module

    import ko = require('knockout');

    export class mainViewModel{

        constructor(){
        }

        public name = ko.observable("John Doe");
        public birthday = ko.observable("1983-01-01");
    }

Conclusion

Everybody are waiting for ECMASript 6 support in all browsers with all sweet things like classes, arrows, modules and so on. Life is too short to wait – let’s use TypeScript today! I’ve tested it in big project and yes sometime it looks a little raw but it’s working and make our life easier with type check and better intellisense.

Knockout.js components. What they are and what they are not

What are components?

Some time ago Knockout.js team released new feature – components. This feature allows developer to build some custom components that will have it’s own view and logic. Registration of component looks almost like binding registration

ko.components.register('mywidget', {
    viewModel: function(params) {
        //Define view model here
        this.title = ko.observable("Hello from component!!!");
    },
    template: '<div data-bind="text: title"></div>'
});

The example below looks very similar to definition of user control in technologies like WPF/Silverlight or even WinForms. We have template to define view of element and view-model to define logic.

Most interesting (for me personally) is usage of these components as custom elements – custom HTML tags. after registrations of my widget in previous examaple you can write following in your HTML code:

<mywidget></mywidget>

Brief description (skip it if you already familiar with components)

And this HTML tag will be replaced with template of the component with applied component view model.

Template can be defined in following way:

  • With existing element id. Template element can be any existing element div or template or anything else.
template: { element: 'my-component-template'}

Element content (only children of element) will be cloned to place where you apply your custom element

  • With exiting element instance
template: { element: getElementById('...') }
  • Directly with string of markup
template: '<div data-bind="text: title"></div>'
  • With array of element instances (elements will be add sequentially)

  • With AMD (Asynchronous Module Definition)

template: { require: 'text!some-template.html' }

Require.js or any other AMD module loader can be used. See https://github.com/amdjs/amdjs-api/blob/master/AMD.md for details.

For view-model configuration you can use following:

  • Constructor function
viewModel: function(params) {
    //Define view model here
    this.title = ko.observable("Hello from component!!!");
}
  • Existing instance of view model
viewModel: { instance: viewModelInstance }
  • Factory function
viewModel: {
              createViewModel: function(params, componentInfo) { 
                                  return new ViewModel(params); 
                               }
           }

Here we have additional parameter componentInfo. This parameter allow us to get access to our custom element with componentInfo.element. But unfortunately we can’t get access to this element before template is applied and analyze it as it was initially added to the document. I’ll describe why I’ve said unfortunately a little later

  • Load view model through AMD
viewModel: { require: 'some/module/name' }
  • Specify whole the component as single AMD module
define(['knockout'], function(ko) {
    return {
        viewModel: function(params) {
           this.title = ko.observable("Hello from component!!!");
        },
        template: '<div data-bind="text: title"></div>'
    };
});

And register it with

ko.components.register('my-component', { require: 'some/module' });

What components are not?

Let’s assume we would like to build a component for bootstrap button with popover. And we would like to open this popover when button is clicked and when another button inside popover is clicked we would like to call some handler in view-model. Something like button with confirmation. And we would like to add custom confirmation template with elements bound to view model.

donate-btn

It would be nice to have component with following syntax

<popover text="Donate" 
		 data-bind="command: makeDonation"
		 title="Enter amount of donation">
	<input class='form-control text-right' type='text' 
               data-bind='value: donationAmount' />
</popover>

But unfortunately it’s not possible. There is no way to read HTML content of the component applied as custom HTML tag, because everything view-model factory, view-model constructor and all other functions are called when template is applied to component and template is required parameter.
Thus you can’t build custom controls with templates inside. Only one possible option is to specify template id as parameter of the your custom control.

<template id='donate-template'>
    <input class='form-control text-right' type='text' 
           data-bind='value: donationAmount' />
</template>

<popover text="Donate" 
		 title="Enter amount of donation" 
		 data-bind="command: makeDonation" 
		 template="donate-template"></popover>

Or use usual binding instead of component to specify template control

<div class="btn btn-xs btn-primary">
   <div data-bind="popover: {title:'Enter ammount', command: makeDonation}"
                   class="hidden">
	 <input class='form-control text-right' type='text' 
                data-bind='value: donationAmount' />
   </div>
   Donate
</div>

More or less equivalent code but imagine how useful this “inline templateing” can be for controls like this http://grid.tesseris.com/Home/Documentation#!/General/general

Let’s hope for the future versions…

Что стоит за async/await и почему опытным разработчикам надо быть осторожными

1. Базовые возможности Task Parallel Library (TPL)

Все возможности TPL базируются на старых Thread и ThreadPool, если точнее, то асинхронное выполнение задач будет производится путем вполнения их через класс ThreadPool. И фактический самый простой способ запустить асинхронную задачу при помощи новых инструментов не слишком отличается от ThreadPool, и выглядит так:

Parallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());

Здесь два лямбда-выражения которые могут быть выполнены параллельно. Однако, как именно это будет происходить и как будет осуществятся синхронизация задач, определяется более новыми механизмами, но, обо всем по порядку.

Основным элементом модели параллельных вычислений является класс Task. Этот класс инкапсулирует в себе некую вычислительную задачу. Никакой “арифметики” задач TPL не предлагает. Другими словами, вы не можете из двух задач собрать цепочку последовательных, или напор параллельных. Разработчики с опытом в TPL скажут, а как же метод ContinueWith? Но дело в том, что этот метод не имеет перегрузки работающей с тасками, он всего лишь позволяет дополнить существующий делегатом. Все равно что дописать в конец кода таска еще одну или несколько строк.

Так же есть статические методы Task.WhenAny и Task.WhenAll, которые создают задачу, завершающуюся после завершения всех или любой из заданных в параметрах задач. Но опять же они не позволяют без дополнительных усилий строить цепочки задач. За это приверженцы Reactive Extensions (Rx) очень ругают TPL.

Использовать Task можно следующим нехитрым способом:

Task task = new Task(() => Console.WriteLine("Hello from taskA."));
task.Start();
// Some code here
task.Wait();
// Some code that should wait before task finish.

Этот же код можно заменить на аналогичный, где метод Task.Run создает и запускает задачу :

Task task = Task.Run(() =&gt; Console.WriteLine("Hello from taskA."));
// Some code here
task.Wait();
// Some code that should wait before task finish.

В описании класса вы найдете функции для ожидания нескольких задач Task.WaitAll и Task.WaitAny. На этом этапе все вроде бы проcто и понятно. Но продолжим наши исследования дальше.

Рассмотрим новый синтаксис C# с await и async. Эти два ключевых слова на самом деле просто облегчают работу с классом Task избавляя разработчика от написания дополнительных методов и другого служебного кода. Для того, чтобы можно было воспользоваться await метод который мы “ждем” должен возвращать Task а метод, в котором мы “ждем” должен быть помечен как async.

Рассмотрим следующий код консольного приложения (Debug используется потому что дальше мы будем этот код запускать в других типах приложений)

static void Main(string[] args)
{
   Debug.WriteLine("Main started in thread {0}", Thread.CurrentThread.ManagedThreadId);
   var task = Task.Run(() =>
   {
      Debug.WriteLine("Task1 started in thread {0}", Thread.CurrentThread.ManagedThreadId);
      Thread.SpinWait(5000000);
      Debug.WriteLine("Task1 finished in thread {0}", Thread.CurrentThread.ManagedThreadId);
   });
   task.Wait();
   Debug.WriteLine("Main finished in thread {0}", Thread.CurrentThread.ManagedThreadId);
}

Результат его работы достаточно ожидаем:

Main started in thread 8
Task1 started in thread 9
Task1 finished in thread 9
Main finished in thread 8

Главный метод запустился в 8-м потоке затем асинхронная задача в 9-м потоке затем завершился 8-й поток.

Перепишем этот код с использованием await и async. Нам придется создать дополнительный метод static async void Run() потому что точку входа помечать async нельзя. Вызов этого метода имеет обычный вид Run();

static void Main(string[] args)
{
   Run();
}
 
static async void Run()
{
   Debug.WriteLine("Main started in thread {0}", Thread.CurrentThread.ManagedThreadId);
   await Task.Run(() =>
   {
      Debug.WriteLine("Task1 started in thread {0}", Thread.CurrentThread.ManagedThreadId);
      Thread.SpinWait(5000000);
      Debug.WriteLine("Task1 finished in thread {0}", Thread.CurrentThread.ManagedThreadId);
   });
 
   Debug.WriteLine("Main finished in thread {0}", Thread.CurrentThread.ManagedThreadId);
}

На первый взгляд все то же самое и те, кто уже немного поработал с await и async, могут подумать, что результат будет таким же. Но результат такой:

Main started in thread 9
Task1 started in thread 10

Куда же делось завершение обоих потоков спросите вы. Для того чтоб разобраться давайте посмотрим на получившуюся сборку при помощи Reflector или ILSpy, отключив при этом декомпиляцию в await и async. Мы увидим, что метод стал выглядеть странно:

private static void Run()
{
   Program.<Run>d__2 <Run>d__;
   <Run>d__.<>t__builder = AsyncVoidMethodBuilder.Create();
   <Run>d__.<>1__state = -1;
   AsyncVoidMethodBuilder <>t__builder = <Run>d__.<>t__builder;
   <>t__builder.Start<Program.<Run>d__2>(ref <Run>d__);
}

И появилась структура private struct <Run>d__2 : IAsyncStateMachine с большим количеством кода в котором попадаются наши строки Debug.WriteLine. Я не буду приводить здесь полный код кому интересно сможете проделать процедуру сами. Смысл этого кода в том, что исходный метод Run был разобран на части и построен некоторый автомат, выполняющий эти части в разных потоках.

Но почему все-таки мы не увидели двух строк с завершением потоков. Ответ на это даст модифицированный код примера. Добавим задержку после вызова Run:

static void Main(string[] args)
{
   Run();
   Thread.SpinWait(10000000);
}
Main started in thread 9
Task1 started in thread 6
Task1 finished in thread 6
Main finished in thread 6

Последняя строка на первый взгляд выглядит более чем странно – метод Main начался в 9-м потоке, а закончился в 6-м. В том же, что и задача “Task1”.

Давайте теперь выполним все то же в WPF приложении, которое имеет единственную кнопку и обработчик нажатия на эту кнопку Button_Click:

private async void Button_Click(object sender, RoutedEventArgs e)
{
   Debug.WriteLine("Main started in thread {0}", Thread.CurrentThread.ManagedThreadId);
   await Task.Run(() =>
   {
      Debug.WriteLine("Task1 started in thread {0}", Thread.CurrentThread.ManagedThreadId);
      Thread.SpinWait(5000000);
      Debug.WriteLine("Task1 finished in thread {0}", Thread.CurrentThread.ManagedThreadId);
   });
   Debug.WriteLine("Main finished in thread {0}", Thread.CurrentThread.ManagedThreadId);
}

Результат будет таким:

Main started in thread 9
Task1 started in thread 6
Task1 finished in thread 6
Main finished in thread 9

Здесь главный метод, почему то, начался и закончился в том же потоке, в 9-м. Если открыть сгенерированную сборку в ILSpy то код будет примерно такой же, не считая инициализации переменных, отвечающих за параметры sender и e имя “главного” метода и содержащего его класса. Выходит, “самые страшные опасения не оправдались код генерируется одинаковый и от типа приложения не зависит. Что же все-таки отличается?

2. SyhchronizationContext и TPL

Причиной разного поведения консольного и WPF приложения были разные контексты синхронизации, разные реализации базового класса SynchronizationContext, заданные в качестве текущего контекста синхронизации. Добавив в оба приложения строку

Debug.WriteLine(SynchronizationContext.Current.GetType().FullName);

видим следующий результат:

– для WPF: System.Windows.Threading.DispatcherSynchronizationContext
– для консоли ничего не видим потому, что SynchronizationContext.Current равен null

При помощи ILSpy можно увидеть, что метод AsyncVoidMethodBuilder.Create(), вызов которого добавлен компилятором в метод Run внутри обращается к контексту синхронизации:

public static AsyncVoidMethodBuilder Create()
{
    return new AsyncVoidMethodBuilder(SynchronizationContext.CurrentNoFlow);
}

Думаю, тут можно остановиться и не копать глубже в код TPL. Таким образом результаты выполнения задач мы будем получать через контекст синхронизации и в WPF мы будем через очередь обработки сообщений попадать в UI поток, а в консольном приложении будет использоваться произвольный другой поток.

Но и это еще не все, есть еще TaskScheduler  который тоже можно поменять и который будет влиять на планирование задач.

Так что начиная использовать async и await постарайтесь забыть все то, что раньше знали о потоках и оперируйте задачами.

На мой взгляд конструкция очень удобная, не нужно думать о синхронизации перенаправлении в поток интерфейса, но с другой стороны столько мест где можно ошибиться, полагаясь на привычные знания о потоках и привычную модель много поточности.