.NET

2010-04-12 5 views
7

में एरलांग-स्टाइल लाइट-वेट प्रक्रियाएं .NET में एरलांग-स्टाइल लाइट-वेट प्रक्रियाओं को लागू करने का कोई तरीका है?.NET

मुझे कुछ परियोजनाएं मिलीं जो एरलांग मैसेजिंग मॉडल (अभिनेता मॉडल) को लागू करती हैं। उदाहरण के लिए, Axum। लेकिन मुझे हल्के वजन की प्रक्रिया कार्यान्वयन के बारे में कुछ भी नहीं मिला। मेरा मतलब है कई प्रक्रियाएं जो एक ओएस-थ्रेड या ओएस-प्रोसेस के संदर्भ में चलती हैं।

उत्तर

10

मुझे लगता है कि एफ # मेलबॉक्स प्रोसेसर वह है जो आप एलेक्सी की तलाश में हैं। मेलबॉक्स प्रोसेसर का उपयोग करके आप हजारों एजेंटों को एक .NET प्रक्रिया में परिभाषित कर सकते हैं जैसे कि आप एरलांग में हजारों हल्के वजन को बढ़ा सकते हैं।

यह MSDN post डॉन सिमे द्वारा एक महान परिचय है।

यदि आप एक एरलंग पृष्ठभूमि से .NET पर आ रहे हैं, तो ध्यान रखें कि आप ओटीपी उपहारों (पर्यवेक्षकों, स्थान पारदर्शिता, मैनेशिया, ...) के बहुत सारे गायब होने जा रहे हैं।

+0

उपयोगी, मानते हुए कि ओपी किसी विशेष भाषा पर केंद्रित नहीं है। –

+0

क्या यह आम तौर पर एक्सम के किसी भी संदर्भ को समझने के लिए सुरक्षित नहीं है "वाहू! कुछ भी जाता है, बच्चे!" :) –

-2

इसका कोई मतलब नहीं है। "एक एकल ओएस थ्रेड या ओएस प्रक्रिया के संदर्भ में चलने वाली एकाधिक प्रक्रिया" तर्कसंगत रूप से अनिवार्य है। यह मूल रूप से एक तार्किक अनुप्रयोग स्तर की बात है - जिसे आप आसानी से .NET में repro कर सकते हैं। लेकिन ओएस स्तर पर "प्रक्रिया के भीतर प्रक्रिया" जैसी कोई चीज नहीं है।

+2

"प्रक्रिया के भीतर प्रक्रिया" - Win32 में फाइबर हैं। – W55tKQbuRu28Q4xv

+2

लेकिन फाइबर स्वयं निर्धारित हैं - THREADS (और अधिकांश मामलों में कोई समझ नहीं है)। एक प्रक्रिया को स्मृति बाधा के रूप में परिभाषित किया जाता है, जिसमें एक फाइबर की कमी होती है। तो, एक फाइबर किसी प्रक्रिया के भीतर एक प्रक्रिया के माध्यम से नहीं है। – TomTom

+2

आपने स्पष्ट रूप से एरलांग के रनटाइम डिज़ाइन को नहीं देखा है। हां, आप एप्लिकेशन स्तर पर एर्लांग जैसी प्रक्रियाओं को कार्यान्वित कर सकते हैं, लेकिन यह सहकारी मल्टीटास्किंग की मात्रा होने की संभावना है, एक तकनीक जिसे मैंने अपने डॉस/विन 16 दिनों के बाद उपयोग नहीं किया है। यदि आपके पास रनटाइम में समर्थन है, तो आप इस प्रभाव को प्रीपेप्टिव मल्टीटास्किंग के साथ प्राप्त कर सकते हैं, लेकिन ऐसा कुछ होगा जो एमएस को .NET में जोड़ना होगा। –

7

सीएलआर होस्ट किया जा सकता है और होस्ट के लिए अपने स्वयं के कार्य अमूर्तता को लागू करने के लिए तंत्र का खुलासा कर सकता है। सैद्धांतिक रूप से, वे धागे, फाइबर, एलडब्ल्यूपी हो सकते हैं - जब तक मेजबान necessaryinterfaces लागू करता है।

इसे प्राप्त करना कुछ मुश्किल है। एसएसएल सर्वर फाइबर मोड में सीएलआर होस्ट करने के लिए एमएस ने इसका मौका लिया।

आखिरी पल में, कुछ तनाव कीड़े थीं, इसलिए उन्होंने Joe Duffy और Dino Vhieland (जो series about writing a custom CLR host that implements its own task abstraction - with fibers - on his blog चलाया) के अनुसार प्लग खींच लिया।
अभी कुछ नलसाजी गायब हैं - ICLRTask::SwitchOut() - और यहां तक ​​कि यदि कोई उस के आसपास हो जाता है, तो भी वही बग जो तनाव परीक्षण पुनरावृत्ति पर एमएस को मारता है, शायद साहसी आत्मा को भी परेशान करेगा।

मान लीजिए कि सभी समस्याओं को किसी तरह से ठीक किया गया है और पूरे रनटाइम फाइबर, एलडब्लूपी, जो कुछ भी चलाने के लिए तैयार हैं। पी/इनवॉक की समस्या अभी भी है जो संभावित रूप से अवरुद्ध संचालन में कॉल कर सकती है। कर्नेल समर्थन के बिना इस प्रकार का शेड्यूल करना मुश्किल है।

यह विंडोज 7 और विंडोज 2008 सर्वर आर 2 के 64 बिट संस्करणों में संबोधित किया गया है। अब User-Mode Scheduling है जो कर्नेल में कॉल ब्लॉक अगर कर्नेल-मोड - शेड्यूलर के विपरीत - उपयोगकर्ता-मोड पर नियंत्रण प्राप्त कर सकता है। साथ ही, ये उपयोगकर्ता-मोड शेड्यूल किए गए थ्रेड अपने स्वयं के टीएलएस के साथ वास्तविक धागे हैं। ये बहुत अच्छे सुधार हैं और फाइबर मोड के कई सिरदर्द दूर हो जाते हैं।

अभी में UMS is utilizedavailable for C++ and is part of the C Runtime Library (CRT) है।
उत्तरार्द्ध का अर्थ है कि आप इसे Visual Studio 2010 के साथ बॉक्स से बाहर उपयोग कर सकते हैं।

+0

पर कोई नज़र डालें, यदि आप इसका उपयोग सीमित करते हैं तो इनमें से कुछ दूर जाते हैं एफ # या किसी अन्य कार्यात्मक भाषा के लिए, ताकि किसी प्रक्रिया के साथ किसी अन्य प्रक्रिया के साथ मिलकर कुछ कठिनाइयों से बचें? –

+0

@Warren: यहां कार्य प्रबंधन वास्तव में किसी थ्रेड/फाइबर/एलडब्लूपी को किसी अन्य की याद में लिखने से रोकता नहीं है। आखिरकार, यह इरादा व्यवहार है - जब भी आप बहु-थ्रेडेड प्रोग्राम शुरू करते हैं तो आप ऐसा करते हैं - सभी धागे प्रक्रिया की स्मृति को एक्सेस और साझा करते हैं। –

+0

@Warren: ... उस ने कहा, साझा राज्य से परहेज या कम करना समांतरता बढ़ाने के महान तरीकों में से एक है। यह सी # में भी किया जा सकता है - हालांकि भाषा लागू नहीं होती है या विशेष रूप से इसे प्रोत्साहित नहीं करती है। –

4

क्या आपने retlang पर एक नज़र डाली है? मैंने केवल इसके बारे में पढ़ा है, लेकिन मैंने इसके साथ कुछ भी नहीं किया है, फिर भी ...

1

एरलांग प्रक्रिया समानांतर तरीके से चलने की विधि की तरह है, लेकिन erlang चर केवल एक बार बाध्य किया जा सकता है, इसलिए यह थ्रेड सुरक्षित है जो सी # में नहीं है।

इसलिए आपको सी #, थ्रेड सुरक्षित और समांतर में दो चीजों की आवश्यकता है।

सी # में सिस्टम है। थ्रेडिंग टास्क, आप वीएम में कई कार्य चला सकते हैं। सी # वीएम इन कार्यों को विभिन्न कामकाजी धागे में शेड्यूलर करेगा।

लेकिन कार्य धागा सुरक्षित नहीं है, आपको अभिनेता नामक एक वर्ग बनाने की जरूरत है, और अभिनेता में राज्य को निजी रखना है।

अभिनेता के पास एक सिस्टम है। थ्रेडिंग। सिंक्रनाइज़ेशन कॉन्टेक्स्ट, और इस तरह के कई async तरीके।

class Actor { 
    public SynchronizationContext _context; 

    private int value1; 
    private Dictionary<> xxx; 
    private List<> xxx; 


    public async Task Method1() { 
     await _context; 

     doSomething(); 
    } 

} 

अन्य अभिनेता इस अभिनेता में async विधि कॉल करते हैं, यह भी कार्य बना होगा, और काम वीएम द्वारा अनुसूचित होगा।

आपको एक प्रतीक्षा करने योग्य और थ्रेड सुरक्षित सिंक्रनाइज़ेशन कॉन्टेक्स्ट को भी लागू करने की आवश्यकता है।

यह एक धागा सुरक्षित संदर्भ है।

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; 
    } 
} 

तो आप कार्य के साथ एक अभिनेता के वर्ग हो और सुरक्षित थ्रेड SynchroniztionContext

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

Awaiter 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(){} 
} 

के लिए awaitable बनाने के जो erlang में प्रक्रिया की तरह।

संबंधित मुद्दे