Giter VIP home page Giter VIP logo

blazorworker's Introduction

NuGet Donate

BlazorWorker

Library that provides a simple API for exposing dotnet web workers in Client-side Blazor.

Checkout the Live demo to see the library in action.

This library is useful for

  • CPU-intensive tasks that merit parallel execution without blocking the UI
  • Executing code in an isolated process

Web workers, simply speaking, is a new process in the browser with a built-in message bus.

To people coming from the .NET world, an analogy for what this library does is calling Process.Start to start a new .NET process, and expose a message bus to communicate with it.

The library comes in two flavours, one built on top of the other:

  • BlazorWorker.BackgroundService: A high-level API that hides the complexity of messaging
  • BlazorWorker.Core: A low-level API to communicate with a new .NET process in a web worker

Installation

Nuget package:

Install-Package Tewr.BlazorWorker.BackgroundService

Add the following line in Program.cs:

  builder.Services.AddWorkerFactory();

And then in a .razor View:

@using BlazorWorker.BackgroundServiceFactory
@inject IWorkerFactory workerFactory

BlazorWorker.BackgroundService

A high-level API that abstracts the complexity of messaging by exposing a strongly typed interface with Expressions. Mimics Task.Run as closely as possible to enable multi-threading.

The starting point of a BlazorWorker is a service class that must be defined by the caller. The public methods that you expose in your service can then be called from the IWorkerBackgroundService interface. If you declare a public event on your service, it can be used to call back into blazor during a method execution (useful for progress reporting).

Each worker process can contain multiple service classes, but each single worker can work with only one thread. For multiple concurrent threads, you must create a new worker for each (see the Multithreading example for a way of organizing this.

Example (see the demo project for a fully working example):

// MyCPUIntensiveService.cs
public class MyCPUIntensiveService {
  public int MyMethod(int parameter) {
    while(i < 5000000) i += (i*parameter);
    return i;
  }
}
// .razor view
@using BlazorWorker.BackgroundServiceFactory
@inject IWorkerFactory workerFactory

<button @onclick="OnClick">Test!</button>
@code {
    int parameterValue = 5;
    
    public async Task OnClick(EventArgs _)
    {
        // Create worker.
        var worker = await workerFactory.CreateAsync();
        
        // Create service reference. For most scenarios, it's safe (and best) to keep this 
        // reference around somewhere to avoid the startup cost.
        var service = await worker.CreateBackgroundServiceAsync<MyCPUIntensiveService>();
        
        // Reference that live outside of the current scope should not be passed into the expression.
        // To circumvent this, create a scope-local variable like this, and pass the local variable.
        var localParameterValue = this.parameterValue;
        var result = await service.RunAsync(s => s.MyMethod(localParameterValue));
    }
}

Setup dependencies

By default, worker.CreateBackgroundServiceAsync<MyService>() will try to guess the name of the dll that MyService resides in (it is usually AssemblyNameOfMyService.dll).

If your dll name does not match the name of the assembly, or if your service has additional dependencies, you must provide this information in WorkerInitOptions. If WorkerInitOptions is provided, the default options are no longer created, so you also have to provide the dll MyService resides in (even if it is in AssemblyNameOfMyService.dll). Examples:

  // Custom service dll, additional dependency
  var serviceInstance = await worker.CreateBackgroundServiceAsync<MyService>(
      new WorkerInitOptions {
        DependentAssemblyFilenames = new [] { "MyService.dll", "MyServiceDependency.dll" }
      }):
      
  // Default service dll, additional dependency
  var serviceInstance = await worker.CreateBackgroundServiceAsync<MyService>(
      new WorkerInitOptions {
        DependentAssemblyFilenames = new [] { 
          $"{typeof(MyService).Assembly.GetName().Name}.dll", 
          "MyServiceDependency.dll" 
        }
      });

blazorworker's People

Contributors

tewr avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.