Using JavaScript Web Workers for Asynchronous Tasks

Intro

JavaScript’s concurrency model until recently has been non-existent. Asynchronous calls like AJAX or event handlers are actually scheduled along a single execution thread, with each event waiting its turn. This is very useful in the browser, where you want to be absolutely sure that you are not manipulating the DOM in a haphazard fashion. UI developers don’t want to have to worry about locking resources, but would rather focus on the end result in the UI.

But what about when you do want to worry about concurrency? What about when you would really like to offload some long running process to your front-end, without having to interrupt the UI thread? What do you do when moving your code to the server and using some signaling method is inconvenient or completely impossible?

Lucky for us modern developers, JavaScript does now provide a solution. WebWorkers are genuinely concurrent thread objects that do not interrupt the UI thread. These objects create OS threads in the background, and can therefore take advantage of multiple cores and other hardware optimizations. This is what we’ll be looking at today.

Creating a Script

WebWorkers take a single JavaScript file and execute it in their own thread and execution context (i.e., self is not the window). This means that the first step is to write the script that you would like to run concurrently.

For this example, we will use a computationally intensive but simple task: number factorization. We’ll use a very basic algorithm since factoring numbers is not the point of this article.

Here is that script. You can call this worker.js.

var percentage = 0;
var factors = [];

// respond to messages from the main thread
self.onmessage = function(e) {
    percentage = 0;
    factors = [];
    findAllFactors(e.data);
};

// loop through all possible prime factors (we'll find non-prime factors as well)
function findAllFactors(num){
    // largest possible prime factor in square root of number
    var max = Math.sqrt(num);
    for(var i = 2; i < max; ++i){
        // our percent complete will be the number of numbers we've
        // checked out fo the total possible numbers
        percentage = Math.ceil((i / max) * 100);
        // this number divides num, so add it to the list
        if(num % i === 0){
            factors.push(i);
        }
        // this number either divides num, or we're done checking, so
        // signal the main thread with our status
        if(num % i === 0 || percentage === 100){
            // post back the list of factors, and our completion percentage
            self.postMessage({
                percentage: percentage,
                factors: factors
            });
        }
    }
}

This script simply takes a number (passed to the worker) and factors it by iterating through all the possible numbers. When it finds a number, it messages the main thread to let it know.

self in a web worker script refers to the worker itself. So by setting onmessage, we are telling the web worker to respond to any messages by factoring the given number.

postMessage does just the opposite. This method sends a message back to the main thread, allowing it to respond to any changes. We do this because the worker itself cannot access the DOM, and if it could, the DOM updates would not occur until after execution had completed, like any other script.

Creating the Main Thread Script

We’ll need a script to create the web worker, and respond to updates. This script will look like the script below.

(function(window, undefined){
    window.loadingIndicator = {
        // 720,720 is a highly composite number (lots of factors, perfect for this example)
        number: 720720 * 720720 * 720720,
        ui: { // our important DOM nodes
            loadingBar: null,
            button: null,
            factors: null
        },
        // our web worker instance
        worker: null,
        // call this from the page
        init: function(){
            this.bindEvents();
        },
        // bind document events
        bindEvents: function(){
            var self = this;
            document.addEventListener('DOMContentLoaded', function(){
                self.setUiElements();
                // bind click event for our button
                self.ui.button.addEventListener('click', self.buttonClicked.bind(self));
                // create the worker
                self.worker = self.createLoadingThread();
            });
        },
        // when we click the button, this adds a span, helping
        // demonstrate the 'non-blocking'ness of the worker
        buttonClicked: function(){
            var span = document.createElement('span');
            var br = document.createElement('br');
            span.innerHTML = 'You clicked me!';
            this.ui.button.parentNode.append(br);
            this.ui.button.parentNode.append(span);
        },
        // set our ui map to nodes
        setUiElements: function(){
            this.ui.loadingBar = document.getElementsByClassName('loading-bar-value')[0];
            this.ui.button = document.getElementsByTagName('button')[0];
            this.ui.factors = document.getElementById('factors');
        },
        // create our worker
        createLoadingThread: function(){
            var worker = new Worker('worker.js');
            worker.onmessage = this.respondToUpdate.bind(this);
            // send worker number to factor
            worker.postMessage(this.number);
            return worker;
        },
        //respond to messages from the worker (new factor found)
        respondToUpdate: function(event){
            // set width to percentage of completion
            this.ui.loadingBar.style.width = String(event.data.percentage) + '%';
            // loading completed
            if(event.data.percentage >= 100){
                this.completed(event);
            }
        },
        // clean up when worker is done
        completed: function(event){
            this.worker.terminate();
            // remove other elements except indicator
            this.ui.button.parentNode.removeChild(this.ui.button);
            // removing shifts entire list up, so we can just keep
            // removing the first element
            var spans = document.getElementsByTagName('span');                
            while(spans.length){
                spans[0].parentNode.removeChild(spans[0]);
            }
            var brs = document.getElementsByTagName('br');
            while(brs.length){
                brs[0].parentNode.removeChild(brs[0]);
            }
            this.ui.factors.innerHTML = 'Factors of ' + 
                this.number + ': ' + 
                event.data.factors.join(', ');
        }
    };
})(window, undefined);

Let’s look at the createLoadingThread method, since this is the most important thing going on here.

On the first line, it creates a web worker, passing it the name of the script we created earlier. Next, it sets the onmessage handler of the web worker to our respondToUpdate method. Don’t confuse this with onmessage in our worker.js file. This onmessage responds only to messages posted from the worker we create to the main thread. This respondToUpdate method in turn updates our loading indicator. When the task has completed, we call the completed method, which calls terminate on the worker.

Lastly, we post a single message to the worker that we created, passing it the number that we want to factor. This will trigger the onmessage handler of the worker, causing it to factor the number and begin posting messages back to our main thread.

Creating a Page

Of course, none of this can execute without a page to run in. The HTML for this example is below.

<!DOCTYPE HTML>
<html>
    <head>
        <style>
            .loading-bar-container {
                width: 200px;
                height: 25px;
                border: 1px solid lightgrey;
            }
            .loading-bar-value {
                background-color: green;
                height: 100%;
                width: 0%;
            }
            button {
                margin-top: 5px;
            }
        </style>
    </head>
    <body>
        <div class="loading-bar-container">
            <div class="loading-bar-value" />
        </div>
        <div id="factors"></div>
        <button>Click me, I still work!</button>
        <script src="main.js"></script>
        <script>
            window.loadingIndicator.init();
        </script>
    </body>
</html>

Putting it All Together

Great! So now we’ve got our worker script, and our script for the main thread. We also have a page to run all of this.

However, that’s not the end of it. In order to run this example without any error message, you will have to set this up under a running web server. Without the web server hosting the page, Chrome and other browsers may throw exceptions because there is no “host”.

Assuming the above is set up, here’s what the page will look like. To test the page, click on the button we created. You’ll notice that the UI is not being interrupted by our factorization. A message is appended for every button click, while the factorization algorithm runs in the background. The loading indicator continues to update as the factorization continues to run.

WebWorker Loading Bar
WebWorker Loading
WebWorker Finished
WebWorker Finished

Conclusion

WebWorkers provide a very simple but very useful API. They provide a clear benefit by allowing you to run computationally intensive tasks without blocking the UI. This leads to a much better user experience, and to much more interactive pages.

The factorization process above can be any long-running calculation that is slowing down your application. Rather than forcing the user to wait, simply put your long-running task into its own script, create a web worker, and respond to its messages until it is completed.

This is a much better user experience than having the UI blocked by some long calculation, so it’s well worth the relatively small effort required to make the change.

If long-running computations are significantly impacting your user’s UI experience, WebWorkers are a great solution, and relatively easy to implement.

Dependency Injection in .NET MVC 5 and WebApi

Intro

Dependency injection is a very popular concept today, usually as part of an MVC web application. Many new frameworks use DI by default, such as AngularJS and .NET Core, but what do those of us working on previous version of .NET MVC do? Well, there’s a solution.

MVC 5 provides many areas where we can inject our own behavior. This is part of the inversion of control philosophy that underlies many libraries. This means that to dependency inject our own services, all we need to do is create our own MVC controller factory and API controller factory, and come up with a method of registering our services.

This article will lead you through that process, along with full code examples.

Getting Started

Solution Structure

The structure should be as follows. Each item should be a project of the same name. The YourApp.Web project should be a .NET MVC web project, and all projects should output a DLL with the same name as the project. The remaining projects should be class libraries. Service should reference Interface, Web should reference Service and Windsor.

  • YourApp.Interface
  • YourApp.Service
  • YourApp.Web
  • YourApp.Windsor

Packages

The first thing you will need is to download a few packages. We will be using Castle.Windsor as our DI container library. Find this package on NuGet and add it to your project.

Castle Windsor NuGet
Castle Windsor NuGet

Structure

In order for DI to be effective, you will need a services “layer” that contains your business logic. This layer should be made of classes which handle your business logic. For the purpose of this example, we will use the interface and implementation below for a single injected service.

This file should go in YourApp.Interface.

namespace YourApp.Interface {
    public interface IDemoService {
        string SayHello();
    }
}

This file should go in YourApp.Service.

namespace YourApp.Service {
    public class DemoService : IDemoService {
        public string SayHello(){
            return "Hello";
        }
    }
}

Web Config

You will need to add this section to your web config.

<section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

You will need to add this information under the castle section. Add one component tag for each service you will be using. You can set the lifestyle as transient for now.

<castle>
    <components>
      <component id="Demo" service="YourApp.Service.IDemoService, YourApp.Interface" type="YourApp.Service.DemoService, YourApp.Service" lifestyle="transient"></component>
    </components>
</castle>

Defining Dependencies

In order for DI to work, we must first define what our dependencies are and what they resolve to. The installer below has been created for this purpose.

Windsor “installers” register the interfaces and their implementations. In this case, we are registering all controllers, all API controllers, and anything in our app configuration file (services above).

The configuration for the IActionInvoker is a little more special. What we’re doing here is specifying our own custom implementation, as well as passing a parameter to the constructor (the parameter is the DI container). You’ll see why we have to do this later.

There are two methods. One registers for the current assembly, which we won’t be using. The other registers using a specified assembly, which we will pass from our web project. The second method is the one you should be concerned with. The first is just a default which implements the necessary interface.

using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Mvc;

namespace YourApp.Windsor {
    public class ServiceInstaller : IWindsorInstaller {
        public void Install(IWindsorContainer container, IConfigurationStore store) {
            container.Register(Classes.FromThisAssembly()
                   .BasedOn<IController>().LifestyleTransient());
            container.Register(Classes.FromThisAssembly()
                   .BasedOn<IHttpController>().LifestyleTransient());
            container.Register(Classes.FromThisAssembly()
                   .BasedOn<FilterAttribute>().LifestyleTransient());
            container.Register(Component.For<IActionInvoker>()
                   .ImplementedBy<WindsorActionInvoker>()
                   .DependsOn(
                      Dependency.OnValue("container", container)
                   ).LifestyleTransient());
            container.Install(Castle.Windsor.Installer.Configuration.FromAppConfig());
        }

        public void InstallFromAssembly(
           IWindsorContainer container, 
           IConfigurationStore store, 
           Assembly assembly
        ) {
            container.Register(Classes.FromAssembly(assembly)
                   .BasedOn<IController>().LifestyleTransient());
            container.Register(Classes.FromAssembly(assembly)
                   .BasedOn<IHttpController>().LifestyleTransient());
            container.Register(Classes.FromAssembly(assembly)
                   .BasedOn<FilterAttribute>().LifestyleTransient());
            container.Register(Component.For<IActionInvoker>()
                   .ImplementedBy<WindsorActionInvoker>()
                   .DependsOn(
                      Dependency.OnValue("container", container)
                   ).LifestyleTransient());
            container.Install(Castle.Windsor.Installer.Configuration.FromAppConfig());
        }
    }
}

Of course, this is just the base class. We’ll inherit from this to pass in our web assembly during installation.

The class below is the installer which will actually be called when the Windsor container is initialized.

using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using YourApp.Interface;
using YourApp.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Mvc;

namespace YourApp.Web.Windsor {
    public class WebServiceInstaller : ServiceInstaller, IWindsorInstaller {
        new public void Install(IWindsorContainer container, IConfigurationStore store) {
            InstallFromAssembly(container, store, Assembly.GetExecutingAssembly());
        }
    }
}

Now we just need to call our installer from the application start method in global.asax.cs.

protected void Application_Start() {
    // install windsor (find our class which implements IWindsorInstaller, and calls the Install method)
    Container = new WindsorContainer();
    Container.Install(FromAssembly.This());
}

Replacing the Controller Factory

ASP.NET MVC uses a controller factory to create instances of each controller when the application receives a request. This is what we will be replacing. Our new factory will resolve the controller type using our DI container, which will inject the services into the constructor.

Creating the New Factory

The new factory is pretty simple. When a controller is done being used, we release it from our container. When a controller is created, we resolve the dependencies through our container, and continue on as usual, calling the default factory methods.

using Castle.MicroKernel;
using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace YourApp.Windsor {
    public class WindsorControllerFactory : DefaultControllerFactory {
        private readonly IWindsorContainer _Container;

        public WindsorControllerFactory(IWindsorContainer container) {
            _Container = container;
        }

        public override void ReleaseController(IController controller) {
            _Container.Release(controller);  // The important part: release the component
        }

        protected override IController GetControllerInstance(
            RequestContext requestContext, 
            Type controllerType
        ) {
            if (controllerType == null) {
                throw new HttpException(404, 
                  string.Format(
                      "The controller for path '{0}' could not be found.", 
                      requestContext.HttpContext.Request.Path
                ));
            }

            Controller controller = (Controller)_Container.Resolve(controllerType);

            // new code
            if (controller != null) {
                // Don't worry about this yet. This will help us inject
                //dependencies into our action filters later
                controller.ActionInvoker = _Container.Resolve<IActionInvoker>();
            }

            return controller;
        }
    }
}

The above code follows the same process as the default controller factory that .NET provides, except that it uses the DI container to resolve the controller. The Resolve method is what injects our dependencies into the constructor.

Modify the Application Start

Now that we have this new controller factory, how will we use it? .NET MVC provides a point of extensibility for this, so we will add it there. Here is the code for this.

protected void Application_Start() {
    // install windsor
    Container = new WindsorContainer();
    Container.Install(FromAssembly.This());
    // use new controller factory
    ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
}

Replacing the Action Invoker

The action invoker is the class which determines how actions are called on a controller. This is the point of extensibility where we will dependency inject properties into the filters.

There is one issue however: by this point in the request lifecycle the action filter objects have already been created, so we can’t use the DI container Resolve method to inject the properties into the constructor.

To solve this problem, we will use the extension method below, which injects the services into an action filter for every matching public property.

using Castle.MicroKernel;
using Castle.MicroKernel.ComponentActivator;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;

namespace YourApp.Windsor {
    public static class WindsorExtension {
        public static void InjectProperties(this IKernel kernel, object target) {
            var type = target.GetType();
            var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var property in props) {
                if (property.CanWrite && kernel.HasComponent(property.PropertyType)) {
                    var value = kernel.Resolve(property.PropertyType);
                    try {
                        property.SetValue(target, value, null);
                    } catch (Exception ex) {
                        var message = string.Format(
                            @"Error setting property {0} on type {1}.
                            See inner exception for more information.", 
                            property.Name, type.FullName
                        );
                        throw new ComponentActivatorException(message, ex, null);
                    }
                }
            }
        }
    }
}

Creating the New Action Invoker

Now we can use this new extension method to loop through the already created action filters and inject their properties, continuing with the default invoke call after we’ve finished injecting our services.

using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace YourApp.Windsor {
    public class WindsorActionInvoker : ControllerActionInvoker {
        readonly IWindsorContainer container;

        public WindsorActionInvoker(IWindsorContainer container) {
            this.container = container;
        }

        protected override ActionExecutedContext InvokeActionMethodWithFilters(
                ControllerContext controllerContext,
                IList filters,
                ActionDescriptor actionDescriptor,
                IDictionary<string, object> parameters) {
            foreach (IActionFilter actionFilter in filters) {
                container.Kernel.InjectProperties(actionFilter);
            }
            return base.InvokeActionMethodWithFilters(
                controllerContext, 
                filters, 
                actionDescriptor, 
                parameters
            );
        }

        protected override AuthorizationContext InvokeAuthorizationFilters(
           ControllerContext controllerContext, 
           IList filters, 
           ActionDescriptor actionDescriptor
        ) {
            foreach (IAuthorizationFilter authFilter in filters) {
                container.Kernel.InjectProperties(authFilter);
            }
            return base.InvokeAuthorizationFilters(
                controllerContext, 
                filters, 
                actionDescriptor
            );
        }
    }
}

Using the New Action Invoker

The controller factory has already been set up to use the new action invoker. That’s what the mysterious line was near the end of our controller factory. To recap, that was this:
controller.ActionInvoker = _Container.Resolve<IActionInvoker>();.
The _Container.Resolve call correctly calls our custom action invoker because we registered it in our installer at the beginning of the tutorial.

Replacing the WebApi Dependency Resolver

The .NET WebApi does not use the same concept of a controller factory (or at least all attempts to use it for DI have been unsuccessful). Instead, we will replace the default dependency resolver with our own.

Creating the New Dependency Resolver

Given that the dependency resolver for .NET WebApi is very similar to what any other DI container does, it is very easy to replace this with our own, using our Windsor DI container instead.

using Castle.MicroKernel;
using Castle.Windsor;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;

namespace YourApp.Windsor {
    public class WindsorDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver {
        private readonly IWindsorContainer _container;

        public WindsorDependencyResolver(IWindsorContainer container) {
            if (container == null) {
                throw new ArgumentNullException("container");
            }

            _container = container;
        }
        public object GetService(Type t) {
            return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
        }

        public IEnumerable<object> GetServices(Type t) {
            return _container.ResolveAll(t).Cast<object>().ToArray();
        }

        public IDependencyScope BeginScope() {
            return new WindsorDependencyScope(_container);
        }

        public void Dispose() {

        }
    }
}

Updating the Application Start

To add our new resolver to the WebApi, we again find ourselves in the application start. here we can set our new resolver.

protected void Application_Start() {
    // install windsor
    Container = new WindsorContainer();
    Container.Install(FromAssembly.This());
    // resolve references for API controllers
    // adding a collection sub-resolver resolves things like List when you've only mapped Type.
    // thismay not be needed, but you should test your code with and without it to be sure
    Container.Kernel.Resolver.AddSubResolver(new CollectionResolver(Container.Kernel, true));
    // replace actual dependency resolver with our own
    var dependencyResolver = new WindsorDependencyResolver(Container);
    GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver;
    // use new controller factory
    ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
}

Update the Application Code

Our solution is now ready for dependency injection, but our controllers and actions do not yet have properties to dependency inject into. We will show the updated structure of our controller and action filter classes.

Updating Controllers

Adding DI to our controllers is pretty easy. Our new controller factory will look for a constructor to inject the services into, matching any types with the services we specified. In this case, that’s our demo service. Our new controller constructor will look like this.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

using YourApp.Interface;

namespace YourApp.Web.Controllers {
    public class HomeController : BaseController {
        private readonly IDemoService _DemoService;

        public HomeController() {

        }

        public HomeController(IDemoService demoService) {
            _DemoService = demoService;
        }

        //... actions here
    }
}

You can now reference _DemoService in any of your action methods. You can also easily replace the implementation, or add new services to be injected into the constructor.

Updating Action Filters

If you remember, our action filters have already been instantiated by the time we can inject the properties, so we had to create an extension method to do this. This problem also rules out using constructor injection, so we will take a different approach: property injection. Here is how that looks for a simple filter.

using YourApp.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace YourApp.Web
{
    public class LayoutFilterAttribute : ActionFilterAttribute {
        // this property is filled in with our service by our special IActionInvoker
        public IDemoService _DemoService { get; set; }

        public LayoutFilterAttribute()
        {
            
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // inject data into layout
            filterContext.Controller.ViewBag.message = _DemoService.SayHello();
        }
    }
}

Conclusion

So that’s all there is to it! It can be quite a lengthy process, but it’s well worth the results, especially if upgrading to .NET Core is not an option, but you’d like to have fine control over your DI process.

The code given here is highly re-usable. If done correctly, you should have a YourApp.Windsor project that you can use in all .NET MVC 5 or WebApi projects for DI, which you can build and use as a dependency for any number of projects without modification.

DI will definitely help you more loosely couple the components of your application, as well as making changes in your application code much easier. You can also dependency inject services into your services, data access objects into your data access layer, and so on, making the pattern highly beneficial, especially when an application may use several implementations of the same service, or may be moved to another data store in the future. DI is good programming practice, and moreover it makes code much more pleasant to work in, and much easier to understand.

Another good takeaway is .NET’s approach to frameworks. They use inversion of control heavily, so there is always a point of extensibility that you can override to provide your own custom functionality. If you ever find yourself wishing a .NET library worked differently, remember: Microsoft has probably left the library heavily open to extension, so there’s no need to force it to do your bidding.

That’s all. I hope this becomes very useful in many people’s projects, it definitely has been for me.