सवाल थ्रेड-सुरक्षित सूची <टी> संपत्ति


मैं एक कार्यान्वयन चाहता हूँ List<T> एक संपत्ति के रूप में जिसे बिना किसी संदेह के थ्रेड-सुरक्षित रूप से इस्तेमाल किया जा सकता है।

कुछ इस तरह:

private List<T> _list;

private List<T> MyT
{
    get { // return a copy of _list; }
    set { _list = value; }
}

ऐसा लगता है कि मुझे संग्रह की प्रतिलिपि (क्लोन) वापस करने की ज़रूरत है, इसलिए यदि कहीं हम संग्रह को पुन: सक्रिय कर रहे हैं और साथ ही संग्रह सेट किया गया है, तो कोई अपवाद नहीं उठाया जाता है।

थ्रेड-सुरक्षित संग्रह संपत्ति को कैसे कार्यान्वित करें?


76
2018-05-03 19:01


मूल


ताले का उपयोग करें, इसे करना चाहिए। - atoMerz
एक थ्रेड-सुरक्षित कार्यान्वयन का उपयोग कर सकते हैं IList<T> (बनाम List<T>)? - Greg
आपने जाँच कर ली है क्या SynchronizedCollection <टी> ? - Saturn Technologies


जवाब:


यदि आप लक्ष्य कर रहे हैं। नेट 4 में कुछ विकल्प हैं System.Collections.Concurrent नाम स्थान

आप उपयोग कर सकते हैं ConcurrentBag<T> इसके बजाय इस मामले में List<T>


131
2018-05-03 19:04



सूची <टी> और शब्दकोश के विपरीत की तरह, ConcurrentBag डुप्लीकेट स्वीकार करता है। - The Light
ConcurrentBag अनियंत्रित संग्रह है, तो विपरीत List<T> यह आदेश की गारंटी नहीं देता है। इसके अलावा आप इंडेक्स द्वारा आइटम तक नहीं पहुंच सकते हैं। - Radek Stromský
@ RadekStromský सही है, और यदि आप एक आदेशित समवर्ती सूची चाहते हैं, तो आप कोशिश कर सकते हैं ConcurrentQueue (फीफो) या ConcurrentStack (LIFO)। - Caio Cunha
शायद SynchronizedCollection <टी> ? - Saturn Technologies
ConcurrentBag IList को लागू नहीं करता है और वास्तव में सूची का थ्रेड सुरक्षित संस्करण नहीं है - Vasyl Zvarydchuk


यहां तक ​​कि सबसे अधिक वोट प्राप्त होने के बावजूद, आमतौर पर कोई नहीं ले सकता है System.Collections.Concurrent.ConcurrentBag<T> के लिए एक थ्रेड-सुरक्षित प्रतिस्थापन के रूप में System.Collections.Generic.List<T> जैसा कि यह है (राडेक स्ट्रॉम्स्की ने पहले ही इसे इंगित किया है) आदेश नहीं दिया गया है।

लेकिन एक वर्ग कहा जाता है System.Collections.Generic.SynchronizedCollection<T> यह पहले से ही फ्रेमवर्क के .NET 3.0 भाग के बाद से है, लेकिन यह उस स्थान पर अच्छी तरह छुपा हुआ है जहां कोई उम्मीद नहीं करता है कि यह बहुत कम ज्ञात है और शायद आपने इसे कभी भी कभी नहीं ठहराया है (कम से कम मैंने कभी नहीं किया)।

SynchronizedCollection<T> असेंबली में संकलित है System.ServiceModel.dll (जो क्लाइंट प्रोफाइल का हिस्सा है लेकिन पोर्टेबल क्लास लाइब्रेरी का नहीं)।

उम्मीद है की वो मदद करदे।


68
2018-05-03 09:15



अच्छा संकेत अभी भी पोर्टेबिलिटी बहुत मायने रखती है। - Xaqron
मैं रोता हूं कि यह मूल lib में नहीं है: {एक सरल सिंक्रनाइज़ संग्रह अक्सर आवश्यक है। - user2864740
इस विकल्प की अतिरिक्त सहायक चर्चा: stackoverflow.com/a/4655236/12484 - Jon Schneider
यह अच्छी तरह छिपा हुआ है क्योंकि सिस्टम में कक्षाओं के पक्ष में बहिष्कृत। चयन। कॉनकुरेंट। - denfromufa
और .NET कोर में उपलब्ध नहीं है - denfromufa


मुझे लगता है कि नमूना बनाना थ्रेडसेफलिस्ट वर्ग आसान होगा:

public class ThreadSafeList<T> : IList<T>
{
    protected List<T> _interalList = new List<T>();

    // Other Elements of IList implementation

    public IEnumerator<T> GetEnumerator()
    {
        return Clone().GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return Clone().GetEnumerator();
    }

    protected static object _lock = new object();

    public List<T> Clone()
    {
        List<T> newList = new List<T>();

        lock (_lock)
        {
            _interalList.ForEach(x => newList.Add(x));
        }

        return newList;
    }
}

आप एक गणक का अनुरोध करने से पहले सूची को क्लोन करते हैं, और इस प्रकार कोई गणना एक प्रतिलिपि से काम कर रही है जिसे चलते समय संशोधित नहीं किया जा सकता है।


15
2018-05-03 19:15



क्या यह एक उथला क्लोन नहीं है? अगर T एक संदर्भ प्रकार है, क्या यह सिर्फ एक नई सूची नहीं लौटाएगा जिसमें सभी मूल वस्तुओं के संदर्भ शामिल हैं? यदि ऐसा है, तो यह दृष्टिकोण अभी भी थ्रेडिंग समस्या का कारण बन सकता है क्योंकि सूची ऑब्जेक्ट्स को सूची के विभिन्न "प्रतियों" के माध्यम से एकाधिक थ्रेडों द्वारा एक्सेस किया जा सकता है। - Joel B
सही, यह एक उथली प्रति है। मुद्दा यह था कि केवल एक क्लोन सेट होना चाहिए जो इसे फिर से सुरक्षित करने के लिए सुरक्षित होगा (इसलिए newListइसमें कोई आइटम जोड़ा या निकाला नहीं गया है जो गणनाकर्ता को अमान्य कर देगा)। - Tejs
क्या _lock स्थिर होना चाहिए? - Mike Ward
एक और विचार क्या यह कार्यान्वयन एकाधिक लेखकों के लिए थ्रेडसेफ है? यदि नहीं, तो शायद इसे रीडसेफलिस्ट कहा जाना चाहिए। - Mike Ward
@ माइकवार्ड - मुझे नहीं लगता कि यह होना चाहिए, सब उदाहरण कब लॉक होगा कोई उदाहरण क्लोन किया जा रहा है! - Josh M.


यहां तक ​​कि स्वीकार्य उत्तर भी ConcurrentBag है, मुझे नहीं लगता कि यह सभी मामलों में सूची का वास्तविक प्रतिस्थापन है, क्योंकि राडेक के जवाब पर टिप्पणी कहती है: "ConcurrentBag अनियंत्रित संग्रह है, इसलिए सूची के विपरीत यह ऑर्डरिंग की गारंटी नहीं देता है। इसके अलावा आप इंडेक्स द्वारा आइटम तक नहीं पहुंच सकते "।

तो यदि आप .NET 4.0 या उच्चतर का उपयोग करते हैं, तो एक वर्कअराउंड का उपयोग किया जा सकता है ConcurrentDictionary सरणी सूचकांक के रूप में पूर्णांक TKey और सरणी मान के रूप में tvalue के साथ। Pluralsight में सूची बदलने की यह अनुशंसित तरीका है सी # समवर्ती संग्रह पाठ्यक्रम। ConcurrentDictionary ऊपर वर्णित दोनों समस्याओं को हल करता है: इंडेक्स एक्सेसिंग और ऑर्डरिंग (हम हुड के तहत हैश टेबल के रूप में ऑर्डर करने पर भरोसा नहीं कर सकते हैं, लेकिन वर्तमान .NET कार्यान्वयन तत्वों को जोड़ने का क्रम बचाता है)।


4
2018-03-31 18:49



कृपया -1 के कारण प्रदान करें - tytyryty
मैंने डाउन-वोट नहीं किया और इसके लिए आईएमओ का कोई कारण नहीं है। आप सही हैं लेकिन कुछ उत्तरों में अवधारणा का पहले ही उल्लेख किया गया है। मेरे लिए, बिंदु था .NET 4.0 में एक नया थ्रेड-सुरक्षित संग्रह जो मुझे पता नहीं था। निश्चित रूप से स्थिति के लिए बैग या संग्रह का उपयोग नहीं किया। +1 - Xaqron
धन्यवाद Xaqron! - tytyryty
इस जवाब में कई समस्याएं हैं: 1) ConcurrentDictionary एक शब्दकोश है, एक सूची नहीं है। 2) यह आपके उत्तर राज्यों के रूप में, पूर्ववर्ती आदेश की गारंटी नहीं है, जो उत्तर देने के आपके कारण बताते हैं। 3) यह एक से जुड़ा हुआ है वीडियो इस उत्तर में प्रासंगिक उद्धरण लाने के बिना (जो कि उनके लाइसेंसिंग के साथ समानता में नहीं हो सकता है)। - jpmc26


आप उपयोग कर सकते हैं:

var threadSafeArrayList = ArrayList.Synchronized(new ArrayList());

थ्रेड सुरक्षित ArrayLsit बनाने के लिए


2
2017-10-08 18:24



किस भाषा के बारे मे बात कर रहे हो? - John Demetriou
जावा? मुझे इसके बारे में कुछ यादों में से एक याद आती है। लेकिन इसे आमतौर पर लिखा जाता है: संग्रह। सिंक्रनाइज़लिस्ट (नया ArrayList ()); - Nick


आप अधिक आदिम का भी उपयोग कर सकते हैं

Monitor.Enter(lock);
Monitor.Exit(lock);

जो लॉक उपयोग करता है (इस पोस्ट को देखें सी # लॉक ब्लॉक में पुन: असाइन किए गए ऑब्जेक्ट को लॉक करना)।

यदि आप कोड में अपवादों की अपेक्षा कर रहे हैं तो यह सुरक्षित नहीं है लेकिन यह आपको निम्न की तरह कुछ करने की अनुमति देता है:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Linq;

public class Something
{
    private readonly object _lock;
    private readonly List<string> _contents;

    public Something()
    {
        _lock = new object();

        _contents = new List<string>();
    }

    public Modifier StartModifying()
    {
        return new Modifier(this);
    }

    public class Modifier : IDisposable
    {
        private readonly Something _thing;

        public Modifier(Something thing)
        {
            _thing = thing;

            Monitor.Enter(Lock);
        }

        public void OneOfLotsOfDifferentOperations(string input)
        {
            DoSomethingWith(input);
        }

        private void DoSomethingWith(string input)
        {
            Contents.Add(input);
        }

        private List<string> Contents
        {
            get { return _thing._contents; }
        }

        private object Lock
        {
            get { return _thing._lock; }
        }

        public void Dispose()
        {
            Monitor.Exit(Lock);
        }
    }
}

public class Caller
{
    public void Use(Something thing)
    {
        using (var modifier = thing.StartModifying())
        {
            modifier.OneOfLotsOfDifferentOperations("A");
            modifier.OneOfLotsOfDifferentOperations("B");

            modifier.OneOfLotsOfDifferentOperations("A");
            modifier.OneOfLotsOfDifferentOperations("A");
            modifier.OneOfLotsOfDifferentOperations("A");
        }
    }
}

इसके बारे में अच्छी चीजों में से एक यह है कि आप संचालन की श्रृंखला की अवधि के लिए लॉक प्राप्त करेंगे (प्रत्येक ऑपरेशन में लॉक करने के बजाए)। जिसका मतलब है कि आउटपुट दाएं हिस्सों में बाहर आना चाहिए (इसका उपयोग बाहरी प्रक्रिया से स्क्रीन पर कुछ आउटपुट प्राप्त कर रहा था)

मुझे वास्तव में सादगी + थ्रेडसेफलिस्ट + की पारदर्शिता पसंद है जो दुर्घटनाओं को रोकने में महत्वपूर्ण बिट करता है


1
2017-08-22 09:43





यदि आप टी की सूची के लिए स्रोत कोड देखते हैं (https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,c66df6f36c131877) आप देखेंगे कि वहाँ एक वर्ग है (जो निश्चित रूप से आंतरिक है - क्यों, माइक्रोसॉफ्ट, क्यों?!?!) टी के सिंक्रनाइज़लिस्ट लिस्ट कहा जाता है। मैं यहां कोड चिपकाने की प्रतिलिपि बना रहा हूं:

   [Serializable()]
    internal class SynchronizedList : IList<T> {
        private List<T> _list;
        private Object _root;

        internal SynchronizedList(List<T> list) {
            _list = list;
            _root = ((System.Collections.ICollection)list).SyncRoot;
        }

        public int Count {
            get {
                lock (_root) { 
                    return _list.Count; 
                }
            }
        }

        public bool IsReadOnly {
            get {
                return ((ICollection<T>)_list).IsReadOnly;
            }
        }

        public void Add(T item) {
            lock (_root) { 
                _list.Add(item); 
            }
        }

        public void Clear() {
            lock (_root) { 
                _list.Clear(); 
            }
        }

        public bool Contains(T item) {
            lock (_root) { 
                return _list.Contains(item);
            }
        }

        public void CopyTo(T[] array, int arrayIndex) {
            lock (_root) { 
                _list.CopyTo(array, arrayIndex);
            }
        }

        public bool Remove(T item) {
            lock (_root) { 
                return _list.Remove(item);
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            lock (_root) { 
                return _list.GetEnumerator();
            }
        }

        IEnumerator<T> IEnumerable<T>.GetEnumerator() {
            lock (_root) { 
                return ((IEnumerable<T>)_list).GetEnumerator();
            }
        }

        public T this[int index] {
            get {
                lock(_root) {
                    return _list[index];
                }
            }
            set {
                lock(_root) {
                    _list[index] = value;
                }
            }
        }

        public int IndexOf(T item) {
            lock (_root) {
                return _list.IndexOf(item);
            }
        }

        public void Insert(int index, T item) {
            lock (_root) {
                _list.Insert(index, item);
            }
        }

        public void RemoveAt(int index) {
            lock (_root) {
                _list.RemoveAt(index);
            }
        }
    }

व्यक्तिगत रूप से मुझे लगता है कि वे एक बेहतर कार्यान्वयन का उपयोग कर जानते थे SemaphoreSlim बनाया जा सकता है, लेकिन यह नहीं मिला।


1
2017-08-12 19:46



+1 पूरे संग्रह को लॉक करना (_root) प्रत्येक पहुंच (पढ़ने / लिखने) में यह धीमा समाधान बनाता है। हो सकता है कि इस वर्ग के लिए आंतरिक रहना बेहतर हो। - Xaqron


मेरा मानना ​​है _list.ToList() आपको एक प्रतिलिपि बना देगा। यदि आपको ऐसा करने की आवश्यकता है तो आप यह भी पूछ सकते हैं:

_list.Select("query here").ToList(); 

वैसे भी, msdn का कहना है कि यह वास्तव में एक प्रति है और न केवल एक संदर्भ है। ओह, और हाँ, आपको सेट विधि में लॉक करने की आवश्यकता होगी क्योंकि अन्य ने बताया है।


0
2018-05-03 19:12





यहां दी गई कक्षा है जिसके लिए आपने पूछा था:

namespace AI.Collections {
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.Threading.Tasks;
    using System.Threading.Tasks.Dataflow;

    /// <summary>
    ///     Just a simple thread safe collection.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <value>Version 1.5</value>
    /// <remarks>TODO replace locks with AsyncLocks</remarks>
    [DataContract( IsReference = true )]
    public class ThreadSafeList<T> : IList<T> {
        /// <summary>
        ///     TODO replace the locks with a ReaderWriterLockSlim
        /// </summary>
        [DataMember]
        private readonly List<T> _items = new List<T>();

        public ThreadSafeList( IEnumerable<T> items = null ) { this.Add( items ); }

        public long LongCount {
            get {
                lock ( this._items ) {
                    return this._items.LongCount();
                }
            }
        }

        public IEnumerator<T> GetEnumerator() { return this.Clone().GetEnumerator(); }

        IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }

        public void Add( T item ) {
            if ( Equals( default( T ), item ) ) {
                return;
            }
            lock ( this._items ) {
                this._items.Add( item );
            }
        }

        public Boolean TryAdd( T item ) {
            try {
                if ( Equals( default( T ), item ) ) {
                    return false;
                }
                lock ( this._items ) {
                    this._items.Add( item );
                    return true;
                }
            }
            catch ( NullReferenceException ) { }
            catch ( ObjectDisposedException ) { }
            catch ( ArgumentNullException ) { }
            catch ( ArgumentOutOfRangeException ) { }
            catch ( ArgumentException ) { }
            return false;
        }

        public void Clear() {
            lock ( this._items ) {
                this._items.Clear();
            }
        }

        public bool Contains( T item ) {
            lock ( this._items ) {
                return this._items.Contains( item );
            }
        }

        public void CopyTo( T[] array, int arrayIndex ) {
            lock ( this._items ) {
                this._items.CopyTo( array, arrayIndex );
            }
        }

        public bool Remove( T item ) {
            lock ( this._items ) {
                return this._items.Remove( item );
            }
        }

        public int Count {
            get {
                lock ( this._items ) {
                    return this._items.Count;
                }
            }
        }

        public bool IsReadOnly { get { return false; } }

        public int IndexOf( T item ) {
            lock ( this._items ) {
                return this._items.IndexOf( item );
            }
        }

        public void Insert( int index, T item ) {
            lock ( this._items ) {
                this._items.Insert( index, item );
            }
        }

        public void RemoveAt( int index ) {
            lock ( this._items ) {
                this._items.RemoveAt( index );
            }
        }

        public T this[ int index ] {
            get {
                lock ( this._items ) {
                    return this._items[ index ];
                }
            }
            set {
                lock ( this._items ) {
                    this._items[ index ] = value;
                }
            }
        }

        /// <summary>
        ///     Add in an enumerable of items.
        /// </summary>
        /// <param name="collection"></param>
        /// <param name="asParallel"></param>
        public void Add( IEnumerable<T> collection, Boolean asParallel = true ) {
            if ( collection == null ) {
                return;
            }
            lock ( this._items ) {
                this._items.AddRange( asParallel
                                              ? collection.AsParallel().Where( arg => !Equals( default( T ), arg ) )
                                              : collection.Where( arg => !Equals( default( T ), arg ) ) );
            }
        }

        public Task AddAsync( T item ) {
            return Task.Factory.StartNew( () => { this.TryAdd( item ); } );
        }

        /// <summary>
        ///     Add in an enumerable of items.
        /// </summary>
        /// <param name="collection"></param>
        public Task AddAsync( IEnumerable<T> collection ) {
            if ( collection == null ) {
                throw new ArgumentNullException( "collection" );
            }

            var produce = new TransformBlock<T, T>( item => item, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount } );

            var consume = new ActionBlock<T>( action: async obj => await this.AddAsync( obj ), dataflowBlockOptions: new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount } );
            produce.LinkTo( consume );

            return Task.Factory.StartNew( async () => {
                collection.AsParallel().ForAll( item => produce.SendAsync( item ) );
                produce.Complete();
                await consume.Completion;
            } );
        }

        /// <summary>
        ///     Returns a new copy of all items in the <see cref="List{T}" />.
        /// </summary>
        /// <returns></returns>
        public List<T> Clone( Boolean asParallel = true ) {
            lock ( this._items ) {
                return asParallel
                               ? new List<T>( this._items.AsParallel() )
                               : new List<T>( this._items );
            }
        }

        /// <summary>
        ///     Perform the <paramref name="action" /> on each item in the list.
        /// </summary>
        /// <param name="action">
        ///     <paramref name="action" /> to perform on each item.
        /// </param>
        /// <param name="performActionOnClones">
        ///     If true, the <paramref name="action" /> will be performed on a <see cref="Clone" /> of the items.
        /// </param>
        /// <param name="asParallel">
        ///     Use the <see cref="ParallelQuery{TSource}" /> method.
        /// </param>
        /// <param name="inParallel">
        ///     Use the
        ///     <see
        ///         cref="Parallel.ForEach{TSource}(System.Collections.Generic.IEnumerable{TSource},System.Action{TSource})" />
        ///     method.
        /// </param>
        public void ForEach( Action<T> action, Boolean performActionOnClones = true, Boolean asParallel = true, Boolean inParallel = false ) {
            if ( action == null ) {
                throw new ArgumentNullException( "action" );
            }
            var wrapper = new Action<T>( obj => {
                try {
                    action( obj );
                }
                catch ( ArgumentNullException ) {
                    //if a null gets into the list then swallow an ArgumentNullException so we can continue adding
                }
            } );
            if ( performActionOnClones ) {
                var clones = this.Clone( asParallel: asParallel );
                if ( asParallel ) {
                    clones.AsParallel().ForAll( wrapper );
                }
                else if ( inParallel ) {
                    Parallel.ForEach( clones, wrapper );
                }
                else {
                    clones.ForEach( wrapper );
                }
            }
            else {
                lock ( this._items ) {
                    if ( asParallel ) {
                        this._items.AsParallel().ForAll( wrapper );
                    }
                    else if ( inParallel ) {
                        Parallel.ForEach( this._items, wrapper );
                    }
                    else {
                        this._items.ForEach( wrapper );
                    }
                }
            }
        }

        /// <summary>
        ///     Perform the <paramref name="action" /> on each item in the list.
        /// </summary>
        /// <param name="action">
        ///     <paramref name="action" /> to perform on each item.
        /// </param>
        /// <param name="performActionOnClones">
        ///     If true, the <paramref name="action" /> will be performed on a <see cref="Clone" /> of the items.
        /// </param>
        /// <param name="asParallel">
        ///     Use the <see cref="ParallelQuery{TSource}" /> method.
        /// </param>
        /// <param name="inParallel">
        ///     Use the
        ///     <see
        ///         cref="Parallel.ForEach{TSource}(System.Collections.Generic.IEnumerable{TSource},System.Action{TSource})" />
        ///     method.
        /// </param>
        public void ForAll( Action<T> action, Boolean performActionOnClones = true, Boolean asParallel = true, Boolean inParallel = false ) {
            if ( action == null ) {
                throw new ArgumentNullException( "action" );
            }
            var wrapper = new Action<T>( obj => {
                try {
                    action( obj );
                }
                catch ( ArgumentNullException ) {
                    //if a null gets into the list then swallow an ArgumentNullException so we can continue adding
                }
            } );
            if ( performActionOnClones ) {
                var clones = this.Clone( asParallel: asParallel );
                if ( asParallel ) {
                    clones.AsParallel().ForAll( wrapper );
                }
                else if ( inParallel ) {
                    Parallel.ForEach( clones, wrapper );
                }
                else {
                    clones.ForEach( wrapper );
                }
            }
            else {
                lock ( this._items ) {
                    if ( asParallel ) {
                        this._items.AsParallel().ForAll( wrapper );
                    }
                    else if ( inParallel ) {
                        Parallel.ForEach( this._items, wrapper );
                    }
                    else {
                        this._items.ForEach( wrapper );
                    }
                }
            }
        }
    }
}

-1
2017-12-22 22:36



वास्तविक कोड पोस्ट करें - Cole Johnson
जब मैं कक्षा अद्यतन करता हूं तो Google ड्राइव पर संस्करण अपडेट हो जाता है। uberscraper.blogspot.com/2012/12/c-thread-safe-list.html - Protiguous
क्यूं कर this.GetEnumerator(); जब @Tejs सुझाव देता है this.Clone().GetEnumerator();? - Cœur
क्यूं कर [DataContract( IsReference = true )]? - Cœur
नवीनतम संस्करण अब गिटहब पर है! github.com/AIBrain/Librainian/blob/master/Collections/... - Protiguous


असल में यदि आप सुरक्षित रूप से गणना करना चाहते हैं, तो आपको लॉक का उपयोग करने की आवश्यकता है।

कृपया इस पर एमएसडीएन देखें। http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx

यहां एमएसडीएन का हिस्सा है कि आपको रुचि हो सकती है:

सार्वजनिक स्थैतिक (विजुअल बेसिक में साझा) इस प्रकार के सदस्य थ्रेड सुरक्षित हैं। किसी भी इंस्टेंस सदस्यों को थ्रेड सुरक्षित होने की गारंटी नहीं है।

जब तक संग्रह संशोधित नहीं किया जाता है, तब तक एक सूची कई पाठकों को समवर्ती रूप से समर्थन दे सकती है। संग्रह के माध्यम से गणना करना आंतरिक रूप से थ्रेड-सुरक्षित प्रक्रिया नहीं है। दुर्लभ मामले में जहां एक गणना एक या अधिक लेखन पहुंच के साथ होती है, थ्रेड सुरक्षा सुनिश्चित करने का एकमात्र तरीका संपूर्ण गणना के दौरान संग्रह को लॉक करना है। संग्रह को पढ़ने और लिखने के लिए संग्रह को कई धागे से एक्सेस करने की अनुमति देने के लिए, आपको अपना सिंक्रनाइज़ेशन लागू करना होगा।


-3
2018-05-03 19:06



बिल्कुल सही नहीं है। आप समवर्ती सेट का उपयोग कर सकते हैं। - ANeves