Cara bekerja dengan ConcurrentBag dan ConcurrentDictionary di .Net

Koleksi serentak di. Net terkandung di dalam Sistem. Koleksi. Ruang nama serentak dan menyediakan pelaksanaan kelas koleksi tanpa kunci dan selamat dari benang. Koleksi benang selamat pertama kali diperkenalkan di. Net 4, dan koleksi pertama kali diperkenalkan sebagai sebahagian dari .Net Framework 1.0 dan tersedia di ruang nama System.Collections

Anda boleh memanfaatkan koleksi serentak untuk bekerja dengan koleksi tanpa perlu menulis kod tambahan untuk penyegerakan benang. Anda boleh melihat artikel saya mengenai ConcurrentStack dan ConcurrentQueue.

SerentakBag

The ConcurrentBag menyediakan koleksi elemen yang tidak disusun tanpa elemen. Berikut adalah senarai kaedah penting kelas ConcurrentBag.

  • Tambah (elemen T) - Kaedah ini digunakan untuk menambahkan elemen ke ConcurrentBag.
  • TryPeek (keluar T) - Kaedah ini digunakan untuk mengambil elemen dari ConcurrentBag tanpa mengeluarkannya.
  • TryTake (keluar T) - Kaedah ini digunakan untuk mengambil elemen dari ConcurrentBag. Perhatikan bahawa kaedah ini mengeluarkan item dari koleksi.

Coretan kod berikut menggambarkan bagaimana anda boleh membuat koleksi ConcurrentBag dan menyimpan item ke dalamnya.

ConcurrentBag concurrentBag = new ConcurrentBag();

  for (int i = 0; i < 10; i++)

    {

        concurrentBag.Add(i);

    }

Sekiranya anda mengambil item dalam koleksi, anda harus menulis kod berikut:

while (concurrentBag.Count > 0)

  {

      Int32 element;

      if (concurrentBag.TryTake(out element))

       {

         Console.WriteLine(element);

       }

  }

Perhatikan bagaimana kaedah TryTake telah digunakan: Ia mengembalikan kebenaran pada kejayaan, sebaliknya sebaliknya. Kaedah TryTake juga mengeluarkan item dari koleksi. Gelung sementara terus dilaksanakan sehingga masa jumlah item dalam koleksi lebih besar daripada sifar. Inilah senarai kod lengkap untuk rujukan anda.

static void Main(string[] args)

        {

            ConcurrentBag concurrentBag = new ConcurrentBag();

            for (int i = 0; i < 10; i++)

            {

                concurrentBag.Add(i);

            }

            while (concurrentBag.Count > 0)

            {

                Int32 element;

                if (concurrentBag.TryTake(out element))

                {

                    Console.WriteLine(element);

                }

            }

            Console.Read();

        }

SerentakDictionary

Kamus ialah koleksi pasangan kunci / nilai generik. Ia lebih pantas daripada Hashtable kerana menghilangkan overhead tinju dan un-boxing. The ConcurrentDictionary terkandung di dalam System.Collections.Conurrent namespace dan mewakili kamus yang selamat untuk thread.

Anggota penting kelas ConcurrentDictionary merangkumi yang berikut:

  • TryAdd: Kaedah ini digunakan untuk menambahkan item dalam instance ConcurrentDictionary. Perhatikan bahawa kaedah ini memberikan pengecualian jika kunci sudah ada dalam koleksi.
  • TryGetValue: Kaedah ini digunakan untuk mengambil item dari koleksi.
  • TryRemove: Kaedah ini digunakan untuk membuang item dari koleksi.
  • TryUpdate: Kaedah ini digunakan untuk mengemas kini kunci tertentu dalam instance ConcurrentDictionary dengan nilai baru yang disediakan.

Coretan kod berikut menunjukkan bagaimana anda boleh membuat instance ConcurrentDictionary dan menambahkan item ke dalamnya:

ConcurrentDictionary obj = new ConcurrentDictionary();

obj.TryAdd("X001", "This is the first value.");

obj.TryAdd("X002", "This is the second value.");

Sekiranya anda sekarang cuba menambahkan item lain tetapi dengan kunci yang sama, ia gagal. Rujuk coretan kod di bawah.

bool success = obj.TryAdd("X002", "This is the third value.");

Nilai pemboleh ubah kejayaan adalah "salah" kerana usaha untuk menambahkan nilai dengan kunci yang sama gagal.

Coretan kod berikut menggambarkan bagaimana anda boleh mengambil item dari koleksi berdasarkan kunci.

string item = null;

bool isExist = obj.TryGetValue("X001", out item);

Sekiranya anda mengambil semua item dalam koleksi, anda boleh menggunakan coretan kod berikut.

foreach(var v in obj)

    {

        Console.WriteLine(v.Key + "---" + v.Value);

    }

Coretan kod berikut menunjukkan cara anda membuang item dari koleksi.

string item = null;

bool result = obj.TryRemove("X001", out item);

Sekiranya anda membuang semua item, potongan kode berikut boleh digunakan sebagai gantinya.

obj.Clear();

Sekarang, pertimbangkan dua kaedah statik berikut.

static void FirstTask(ConcurrentDictionary obj)

        {

            for (int i = 0; i < 10; ++i)

            {

                obj.TryAdd(i.ToString(), i.ToString());

                Thread.Sleep(100);

            }

        }

        static void SecondTask(ConcurrentDictionary obj)

        {

            Thread.Sleep(1000);

            foreach (var item in obj)

            {

                Console.WriteLine("Key: "+item.Key + "   Value: " + item.Value);

                Thread.Sleep(100);

            }

        }

Begini caranya anda dapat melaksanakan dua kaedah di atas pada dua kejadian Tugas secara serentak - satu untuk menyimpan nilai ke dalam koleksi dan yang lain untuk membaca nilai dari koleksi.

ConcurrentDictionary obj = new ConcurrentDictionary();

Task firstTask = Task.Run(() => FirstTask(obj));           

Task secondTask = Task.Run(() => SecondTask(obj));           

try

{

  Task.WaitAll(firstTask, secondTask);

}

catch (AggregateException ex)

{

   //Write your own code here to handle exception

}

Sekiranya anda melaksanakan kod di atas, pengecualian tidak akan dilemparkan kerana koleksi di sini adalah selamat dari utas.