Erlang lightweight processes in .NET.

Is there a way to implement Erlang lightweight processes in .NET?

I found several projects that implement the Erlang messaging model (actor model). For example, Axum . But I did not find anything about implementing lightweight processes . I mean several processes that run in the context of a single OS thread or OS process.

+7
c # concurrency erlang
source share
5 answers

I think F # MailboxProcessor is what you are looking for Alexey. Using MailboxProcessor you can define tens of thousands of agents within a single .NET process, since you can create tens of thousands of lightweight processes in Erlang.

This MSDN post from Don Syme is a great introduction.

If you come to .NET from the Erlang background, keep in mind that you lacked the many positive qualities of OTP (supervisors, location transparency, mnesia, ...).

+10
source share

The CLR can be hosted and provides mechanisms for the host to implement its own abstraction of the task. Theoretically, they can be threads, fibers, LWP - anything, as long as the host implements the necessary interfaces .

The correct decision is somewhat complicated. MS took the opportunity to host the CLR in SQL Server Fiber Channel mode.

There were some stress errors at the last moment, so they pulled a plug-in on it in accordance with Joe Duffy and Dino Vhieland (who spent a series on creating a custom CLR node that implements its own abstraction of the task - using fiber - in his blog ).
Right now some kind of plumbing is ICLRTask::SwitchOut() - ICLRTask::SwitchOut() - and even if you get around this, the same errors that fall into MS during the iteration of the stress test are likely to be haunted by an adventurous soul.

Suppose for a moment that all problems are somehow fixed, and the entire runtime is ready to work on fibers, LWP, whatever. There is still a P / Invoke issue that could potentially cause blocking operations. This kind of planning is difficult to do without kernel support.

This is covered in 64-bit versions of Windows 7 and Windows 2008 Server R2. Now there is User-Mode Scheduling , which can return control to user mode - unlike the kernel mode scheduler, if it blocks a call to the kernel. In addition, these scheduled user-mode flows are real flows with their own TLS. These are great improvements, and many headaches in fiber mode disappear.

Right now, UMS is used in the Concurrency Runtime , which is available for C ++ and is part of the runtime library (CRT). The latter means that you can use it out of the box with Visual Studio 2010 .

+7
source share

Have you seen retlang ? I only read about it, but I did not do anything with it, but ...

+4
source share

The Erlang process is similar to the executed method in parallel, but the erlang variable can only be bound once, so it is thread safe, which is not in C #.

so you need two things in C #, thread safety and concurrency.

C # has System.Threading.Task, you can run many tasks in vm. C # vm will schedule this task in different workflows.

But the task is not thread safe, you need to create a class called "Actor" and put the state in Actor.

The actor has System.Threading.SynchronizationContext and many async methods, for example.

 class Actor { public SynchronizationContext _context; private int value1; private Dictionary<> xxx; private List<> xxx; public async Task Method1() { await _context; doSomething(); } } 

When other Actors call the asynchronization method in this Actor, it will create a task and the task will be scheduled using vm.

You also need to implement the expected and thread safe SynchronizationContext.

it is a safe stream.

 public class ActorSynchronizationContext : SynchronizationContext { private readonly SynchronizationContext _subContext; private readonly ConcurrentQueue<Action> _pending = new ConcurrentQueue<Action>(); private int _pendingCount; public ActorSynchronizationContext(SynchronizationContext context = null) { this._subContext = context ?? new SynchronizationContext(); } public override void Post(SendOrPostCallback d, object state) { if (d == null) { throw new ArgumentNullException("SendOrPostCallback"); } _pending.Enqueue(() => d(state)); if (Interlocked.Increment(ref _pendingCount) == 1) { try { _subContext.Post(Consume, null); } catch (Exception exp) { LogHelper.LogUnhandleException(exp.ToString()); } } } private void Consume(object state) { var surroundContext = Current; SetSynchronizationContext(this); do { Action a; _pending.TryDequeue(out a); try { a.Invoke(); } catch (Exception exp) { //Debug.LogError(exp.ToString()); LogHelper.LogUnhandleException(exp.ToString()); } } while (Interlocked.Decrement(ref _pendingCount) > 0); SetSynchronizationContext(surroundContext); } public override void Send(SendOrPostCallback d, object state) { throw new NotSupportedException(); } public override SynchronizationContext CreateCopy() { return this; } } 

make SynchroniztionContext expected

 public static class SynchroniztionContextExtensions { public static SynchronizationContextAwaiter GetAwaiter (this SynchronizationContext context) { if(context == null) throw new ArgumentNullException("context"); return new SynchronizationContextAwaiter(context); } } 

Awaiter for SynchronizationContext

 public sealed class SynchronizationContextAwaiter : INotifyCompletion { private readonly SynchronizationContext _context; public SynchronizationContextAwaiter(SynchronizationContext context) { if(context == null ) throw new ArgumentNullException("context"); _context = context; } public bool IsCompleted { get { //已经在当前上下文里面了,就不需要再次切换上下文return SynchronizationContext.Current == _context; } } /// <summary> /// 将Action 任务调度到 _context 控制的线程里面去执行/// /// var temp = e.GetAwaiter(); /// </summary> /// <param name="action">Action.</param> public void OnCompleted(Action action) { _context.Post(x=>action(), null); } public void GetResult(){} } 

then you get an Actor class with task security and thread, which are like a process in erlang.

+1
source share

It does not make sense. "Several processes that run in the context of a single OS thread or OS process" are logically inconclusive. This is basically an application level logical thing that you can easily reproduce in .NET. But at the OS level, there is no such thing as a "process inside a process."

-2
source share

All Articles