কোন একক, নির্দিষ্ট অবজেক্টটি কনক্রন্টব্যাগ <> থেকে সরানো যায়?


109

ConcurrentBag<T>.NET 4- এ নতুন দিয়ে আপনি কেবল যখন TryTake()এবং যখন TryPeek()উপলব্ধ থাকবেন তখন কীভাবে আপনি এটি থেকে একটি নির্দিষ্ট, নির্দিষ্ট অবজেক্টটি সরিয়ে ফেলবেন?

আমি ব্যবহারের কথা ভাবছি TryTake()এবং তারপরে ফলস্বরূপ অবজেক্টটি তালিকায় আবার যুক্ত করতে চাই যদি আমি এটি সরাতে না চাই তবে আমার মনে হয় আমি কিছু অনুপস্থিত হতে পারি। এটি কি সঠিক উপায়?

উত্তর:


89

সংক্ষিপ্ত উত্তর: আপনি এটি একটি সহজ উপায়ে করতে পারবেন না।

কনক্র্যান্টব্যাগ প্রতিটি থ্রেডের জন্য একটি থ্রেড স্থানীয় সারি রাখে এবং এটির নিজস্ব সারি খালি হয়ে গেলে এটি কেবল অন্য থ্রেডের সারিগুলিতে কেবল তাকান। আপনি যদি কোনও আইটেম সরান এবং এটি আবার রেখে দেন তবে আপনি যে আইটেমটি সরিয়ে ফেলবেন সেটি আবার একই আইটেম হতে পারে। কোনও গ্যারান্টি নেই যে বারবার আইটেমগুলি সরিয়ে ফেলা এবং সেগুলি ফিরিয়ে দেওয়া আপনাকে সমস্ত আইটেমগুলির মধ্যে পুনরাবৃত্তি করতে দেয়।

আপনার জন্য দুটি বিকল্প:

  • সমস্ত আইটেম সরান এবং সেগুলি মনে রাখুন, যতক্ষণ না আপনি মুছে ফেলতে চান এমন একটি খুঁজে পাওয়া যায়, তারপরে অন্যটিকে পিছনে রাখুন। নোট করুন যে দুটি থ্রেড একই সাথে এটি করার চেষ্টা করলে আপনার সমস্যা হবে।
  • আরও উপযুক্ত ডেটা কাঠামো যেমন কনক্রন্টড অভিধান অভিধান ব্যবহার করুন ।

9
সিঙ্ক্রোনাইজড কালেকশনও উপযুক্ত বিকল্প হতে পারে।
— ILIA ব্রুডনো

2
@ আইআইএলব্রোডনো - আপনার উত্তরটি দেওয়া উচিত!
— ডেনিস

2
এফওয়াইআই, সিঙ্ক্রোনাইজড কালেকশন। নেট কোরটিতে উপলভ্য নয়। এই মন্তব্যের তারিখ অনুসারে, সিস্টেম.কলেশন.কন্ট্রেন্ট টাইপগুলি। নেট কোর ভিত্তিক বাস্তবায়নের জন্য বর্তমান পন্থা।
— ম্যাথু স্নাইডার

2
আমি নিশ্চিত না যে নেট নেট এর কোন সংস্করণ ব্যবহৃত হচ্ছে, তবে আমি .NET কোর ২.১ এসডিকে এবং সিঙ্ক্রোনাইজড কালেকশন ভিত্তিক একটি প্রকল্পে কাজ করছি the এখন জেনেরিক নেমস্পেসে উপলব্ধ।
— লুকাস লেব্ল্যাঙ্ক

15

আপনি পারবেন না। এটি একটি ব্যাগ, এটি অর্ডার করা হয় না। আপনি এটি পিছনে রাখলে, আপনি কেবল একটি অন্তহীন লুপে আটকে যাবেন।

আপনি একটি সেট চান। আপনি সাম্প্রতিক অভিধানের সাহায্যে একটি অনুকরণ করতে পারেন। অথবা একটি হ্যাশসেট যা আপনি নিজেকে একটি লক দিয়ে সুরক্ষিত করেন।


8
দয়া করে প্রসারিত করুন। অন্তর্নিহিত সমকালীন অভিধানে কী হিসাবে ব্যবহার করবেন?
— ডেনিস স্কিডমোর

2
ঠিক আছে, আমি ধরে নিই যে কীটি আপনি যে ধরণের অবজেক্টটি সংরক্ষণ করার চেষ্টা করছেন সেটি হবে এবং তারপরে মানটি কিছু প্রকারের সংগ্রহ হবে। HashSetতিনি বর্ণনা হিসাবে এটি "অনুকরণ" হবে ।
— ম্যাথিয়াস লাইককেগার্ড লরেঞ্জেন 21

5

কনক্র্যান্টব্যাগ একটি তালিকা পরিচালনা করতে দুর্দান্ত যেখানে আপনি আইটেমগুলি যুক্ত করতে এবং অনেক থ্রেড থেকে অঙ্ক করতে পারেন, তার নামটি প্রস্তাবিত হওয়ার সাথে সাথে শেষ পর্যন্ত এটিকে ফেলে দিন :)

যেমনটি মার্ক বাইয়ার্স বলেছিলেন , আপনি একটি নতুন কনক্রন্টব্যাগটি পুনরায় তৈরি করতে পারবেন যাতে আপনি যে আইটেমটি সরাতে চান তা এতে নেই, তবে আপনাকে এটিকে লক ব্যবহার করে একাধিক থ্রেড হিট থেকে রক্ষা করতে হবে। এটি একটি এক-লাইনার:

myBag = new ConcurrentBag<Entry>(myBag.Except(new[] { removedEntry }));

এটি কাজ করে এবং কনক্র্যান্টব্যাগটির জন্য তৈরি করা সেই চেতনার সাথে মেলে।


9
আমি মনে করি এই উত্তরটি বিভ্রান্তিকর। পরিষ্কার হওয়ার জন্য, এটি পছন্দসই অপসারণ অপারেশনে কোনও থ্রেড সুরক্ষা সরবরাহ করে না। এবং এটিকে চারপাশে একটি লক স্থাপন করা সমকালীন সংগ্রহ ব্যবহারের উদ্দেশ্যকে পরাস্ত করে।
— ILIA ব্রুডনো

1
আমি রাজী. ঠিক আছে, কিছুটা স্পষ্ট করার জন্য, কনক্র্যান্টব্যাগটি তৈরি করা হয়েছে যখন এটি সম্পন্ন হবে তখন সম্পূর্ণ সামগ্রীর সাথে পরিপূর্ণ, গণনা করা এবং ফেলে দেওয়া হবে। খনি-সহ কোনও প্রচেষ্টা - কোনও আইটেম সরানোর জন্য একটি নোংরা হ্যাক হবে। কমপক্ষে আমি একটি উত্তর দেওয়ার চেষ্টা করেছি, যদিও সমকালীন অভিধানের মতো আরও ভাল সমবর্তী সংগ্রহের ক্লাস ব্যবহার করা সবচেয়ে ভাল।
— ল্যারি

4

চিহ্নটি সঠিক যে সমকালীন অভিধানটি আপনার ইচ্ছা অনুযায়ী কাজ করবে। আপনি যদি এখনও নিখুঁতভাবে কনক্র্যান্টব্যাগটি ব্যবহার করতে চান তবে দক্ষ মন নয়, আপনাকে সেখানে পৌঁছে দেবে।

var stringToMatch = "test";
var temp = new List<string>();
var x = new ConcurrentBag<string>();
for (int i = 0; i < 10; i++)
{
    x.Add(string.Format("adding{0}", i));
}
string y;
while (!x.IsEmpty)
{
    x.TryTake(out y);
    if(string.Equals(y, stringToMatch, StringComparison.CurrentCultureIgnoreCase))
    {
         break;
    }
    temp.Add(y);
}
foreach (var item in temp)
{
     x.Add(item);
}


1
public static void Remove<T>(this ConcurrentBag<T> bag, T item)
{
    while (bag.Count > 0)
    {
        T result;
        bag.TryTake(out result);

        if (result.Equals(item))
        {
            break; 
        }

        bag.Add(result);
    }

}

ConcurrentBagএকটি আনর্ডারড সংগ্রহ, তবে আপনার কোডটি এটি প্রত্যাশা করে bag.TryTakeএবং bag.Addফিফোর পদ্ধতিতে কাজ করে। আপনার কোড ধরে নেয় যা bagএতে অন্তর্ভুক্ত রয়েছে item, এটি সন্ধান itemনা করা অবধি লুপ হয় bag। কোড কেবল উত্তরগুলি নিরুৎসাহিত করা হয়, আপনার সমাধানটি ব্যাখ্যা করা উচিত।
— জিডাভিড

-1

এটি আমার এক্সটেনশন ক্লাস যা আমি আমার প্রকল্পগুলিতে ব্যবহার করছি। এটি সাম্প্রতিক ব্যাগ থেকে একক আইটেম অপসারণ করতে পারে এবং ব্যাগ থেকে আইটেমের তালিকাও সরাতে পারে

public static class ConcurrentBag
{
    static Object locker = new object();

    public static void Clear<T>(this ConcurrentBag<T> bag)
    {
        bag = new ConcurrentBag<T>();
    }


    public static void Remove<T>(this ConcurrentBag<T> bag, List<T> itemlist)
    {
        try
        {
            lock (locker)
            {
                List<T> removelist = bag.ToList();

                Parallel.ForEach(itemlist, currentitem => {
                    removelist.Remove(currentitem);
                });

                bag = new ConcurrentBag<T>();


                Parallel.ForEach(removelist, currentitem =>
                {
                    bag.Add(currentitem);
                });
            }

        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }

    public static void Remove<T>(this ConcurrentBag<T> bag, T removeitem)
    {
        try
        {
            lock (locker)
            {
                List<T> removelist = bag.ToList();
                removelist.Remove(removeitem);                

                bag = new ConcurrentBag<T>();

                Parallel.ForEach(removelist, currentitem =>
                {
                    bag.Add(currentitem);
                });
            }

        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
}

এটি কার্যকর হতে পারে তা বিশ্বাস করা শক্ত কারণ আপনি স্থানীয় ভেরিয়েবলে নতুন কনকন্টারব্যাগ তৈরি করছেন, তবে আমি নিশ্চিত নই। কোন পরীক্ষা?
— shtse8

3
না, এটি কাজ করে না। এটি কীভাবে কাজ করবে, আপনি কেবল একটি নতুন রেফারেন্স তৈরি করছেন। পুরানোটি এখনও পুরানো অবজেক্টের দিকে ইঙ্গিত করছে .... আপনি যদি "রেফ" এর সাথে কাজ করেন তবে এটি কাজ করবে
— টমাস ক্রিস্টফ

-5
public static ConcurrentBag<String> RemoveItemFromConcurrentBag(ConcurrentBag<String> Array, String Item)
{
    var Temp=new ConcurrentBag<String>();
    Parallel.ForEach(Array, Line => 
    {
       if (Line != Item) Temp.Add(Line);
    });
    return Temp;
}

-13

কেমন:

bag.Where(x => x == item).Take(1);

এটি কার্যকর, আমি নিশ্চিত না কতটা দক্ষতার সাথে ...


এটি ব্যাগ থেকে কিছুই সরিয়ে দেয় না। আপনি যে আইটেমটি পুনরুদ্ধার করছেন তা ব্যাগের মধ্যেই থেকে যায়।
— কিথ

3
"ব্যাগ = নতুন কনকোর্ন্টব্যাগ (ব্যাগ। কোথায় (x => x! = আইটেম)) হওয়া উচিত"
— এটিকোট

4
@ কোটোট, এই লাইনটি আমাকে হাসিয়েছে
— পেরেক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.