Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run .NET in a worker thread #5475

Closed
SteveSandersonMS opened this issue Feb 19, 2018 · 13 comments
Closed

Run .NET in a worker thread #5475

SteveSandersonMS opened this issue Feb 19, 2018 · 13 comments
Labels
affected-very-few This issue impacts very few customers area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one not-on-roadmap severity-minor This label is used by an internal tool
Milestone

Comments

@SteveSandersonMS
Copy link
Member

It will be a while before we get to this, but various parts of the architecture are already designed with this in mind.

We should support running Blazor in two modes, auto-selecting which one is best for the current user's browser:

  • On the browser's main JS thread, which is necessary for older browsers that don't support WebWorker. The .NET/JS interop can continue using shared memory if we find it's necessary to have good perf on those older browsers (and thread safety is not difficult because it's all synchronous).
  • In a web worker (background thread) on more up-to-date browsers. The .NET/JS interop will need to work by serializing any data that is being transferred rather than passing pointers [1].

This will be advantageous because then, even if your .NET code does something that locks up the CPU (such as a GC cycle), the UI will remain perfectly smooth (e.g., during animations or scrolling, or while the user is typing quickly into a textbox).

The existing UI update mechanism is designed around transferring batches of minimal diffs from .NET to JS, so it shouldn't be hugely difficult to have it express those diffs as serialized data rather than pointers into the WASM memory space. We'll have to be careful around things like event handling to ensure that the asynchrony can't result in inconsistency of behaviour versus the synchronous single-threaded model. For example, we will need to force all event delivery to be async as far as the JS side is concerned, even in the non-worker-thread case.

[1] Strictly speaking, we could also do it with shared memory on even newer browsers that support SharedArrayBuffer. But if we can get satisfactory perf without this, it would be better to serialize because it would mean fewer combinations of browser scenarios, and saves us having to deal with potentially complex thread-safety concerns on the .NET side.

@vibeeshan025
Copy link

vibeeshan025 commented Feb 25, 2018

The .NET/JS interop will need to work by serializing any data that is being transferred rather than passing pointers [1]

Since new web browsers support SharedArrayBuffer it's better to support that.

If multiple browser combination is a problem then we can have only two combinations as below.

  1. On the browser's main JS thread mode
  2. Full thread support with shared memory. Any browser that doesn't support shared array buffer will work on mode 1.

Maybe for C# dynamic objects we can use serialization since we can't predict the size of the object in the compile time.

It's like we are designing it for the future with full .net like threading support ( 1 or 0 no gray), we should not compromise on performance for compatibility.

We have enough js frameworks out there, the real game changer should provide a multitude of performance improvement over what existing frameworks provide.

I see this as a framework going to crush any js framework out there. Angular, react Vue etc.

@wanton7
Copy link

wanton7 commented Feb 25, 2018

@vibeeshan025 so you want to limit support for web worker just to use SharedArrayBuffer? That doesn't make no sense what so ever.
First support what works in most browsers so that you get smoothest possible Blazor experience in many browsers as possible to compete with existing SPA frameworks/libraries. Then later think about adding more choices for serialization.

SharedArrayBuffer was also disabled in browsers 5 January, 2018 due to Spectre vulnerability and it's probably still be disabled.

@SteveSandersonMS
Copy link
Member Author

Thanks for the thoughts from both of you!

@vibeeshan025 I think your suggestion is interesting and has merit. We'll have to see what the actual perf effects of different choices are, and what level of browser support exists for SharedArrayBuffer, when we get to implementing this.

@joeizy
Copy link

joeizy commented Mar 8, 2018

NativeScript opted to follow a single threaded by default model for JS and native code on mobile devices. This gave them the ability to do some interesting things with native APIs that aren’t achieved in other run times such as ReactNative. It also simplified the programming model because single UI thread is what you expect when working with UI unless you explicitly dispatch another thread.

I’m not familiar enough with Blazor or WebAssembly to comment pros / cons but I thought it would be interesting to bring two existing examples that were implemented differently and have their associated consequences.

One that stands out which may be relevant is custom animations. Not being on the UI thread creates a lot of back and forth if you’re trying to do real-time or frequent updates to UI elements such as in custom animation scenarios. Painful in early versions of ReactNative and my understanding is direct byproduct running on a background thread.

@joeizy
Copy link

joeizy commented Mar 8, 2018

https://developer.telerik.com/featured/benefits-single-threading-model-nativescript/

@Thaina
Copy link

Thaina commented Apr 8, 2018

I am more align with UI thread for blazor, and using webworker thread only with intentionally multithread API (such as Threading and Concurrent). So we would have fully intended code to control UI with blazor

@galvesribeiro
Copy link
Member

Just a reminder... SharedArrayBuffer is disabled on all major browsers since specter disclosure...

@cician
Copy link

cician commented Jun 2, 2018

I'd love the ability to run .net code in a worker thread. Not just for concurrency, but in order to actually isolate code in a separate wasm module since I want to dynamically load and unload assemblies, which doesn't otherwise seem possible right now as far as I can tell (no AppDomains or AssemblyLoadContext). Complete isolation is actually desirable for my use case (compiling and running potentially untrusted code).
That being said I'm eagerly waiting for actual multi-threading with shared memory.

@vibeeshan025
Copy link

Google chrome started implementing threads in c++ style https://developers.google.com/web/updates/2018/10/wasm-threads

@aspnet-hello aspnet-hello transferred this issue from dotnet/blazor Dec 17, 2018
@aspnet-hello aspnet-hello added this to the Backlog milestone Dec 17, 2018
@aspnet-hello aspnet-hello added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates enhancement This issue represents an ask for new feature or an enhancement to an existing one area-blazor Includes: Blazor, Razor Components labels Dec 17, 2018
@mkArtakMSFT mkArtakMSFT removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels May 9, 2019
@Tewr
Copy link

Tewr commented Mar 23, 2020

@cician, @vibeeshan025 would you mind giving some feedback on this library, it partially fit the usecase. It's without shared memory, just using messages.

@andersson09
Copy link

Is this still in the pipeline?

@MarioBolivar
Copy link

Hello!

Is this still in the pipeline? As a stop-gap, what is the best solution for handling long running jobs so that they don't lock the UI thread? I've seen suggestions of breaking down the jobs into smaller slices and doing something like Task.Delay() between the slices to catch the UI up. Is this the best/only solution at the moment?

@SteveSandersonMS
Copy link
Member Author

This issue is a bit confusing, so I'm closing it in favour of #28360

This issue talks about running .NET in a worker thread, but that wouldn't provide actual multithreading - it would just run .NET code in a single-threaded way but off the DOM UI thread. I don't think that's what anyone here is really asking for, and if that is what someone wants, I expect they could do it on their own today (but would have to figure out for themselves how to update the DOM in this case).

@MarioBolivar For true multithreading, the issue you want is #28360. That's likely to land in .NET 7 at the earliest. In the meantime yes, you should use typical task-batching techniques to split up long jobs into multiple pieces, each of which can run asynchronously. Generally you can use Task.Yield() instead of Delay for slightly cleaner results.

@ghost ghost locked as resolved and limited conversation to collaborators Apr 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affected-very-few This issue impacts very few customers area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one not-on-roadmap severity-minor This label is used by an internal tool
Projects
None yet
Development

No branches or pull requests