Is HashSet thread safe as a value of ConcurrentDictionary<TKey, HashSet>?












4














If I have the following code:



var dictionary = new ConcurrentDictionary<int, HashSet<string>>();

foreach (var user in users)
{
if (!dictionary.ContainsKey(user.GroupId))
{
dictionary.TryAdd(user.GroupId, new HashSet<string>());
}

dictionary[user.GroupId].Add(user.Id.ToString());
}


Is the act of adding an item into the HashSet inherently thread safe because HashSet is a value property of the concurrent dictionary?










share|improve this question





























    4














    If I have the following code:



    var dictionary = new ConcurrentDictionary<int, HashSet<string>>();

    foreach (var user in users)
    {
    if (!dictionary.ContainsKey(user.GroupId))
    {
    dictionary.TryAdd(user.GroupId, new HashSet<string>());
    }

    dictionary[user.GroupId].Add(user.Id.ToString());
    }


    Is the act of adding an item into the HashSet inherently thread safe because HashSet is a value property of the concurrent dictionary?










    share|improve this question



























      4












      4








      4







      If I have the following code:



      var dictionary = new ConcurrentDictionary<int, HashSet<string>>();

      foreach (var user in users)
      {
      if (!dictionary.ContainsKey(user.GroupId))
      {
      dictionary.TryAdd(user.GroupId, new HashSet<string>());
      }

      dictionary[user.GroupId].Add(user.Id.ToString());
      }


      Is the act of adding an item into the HashSet inherently thread safe because HashSet is a value property of the concurrent dictionary?










      share|improve this question















      If I have the following code:



      var dictionary = new ConcurrentDictionary<int, HashSet<string>>();

      foreach (var user in users)
      {
      if (!dictionary.ContainsKey(user.GroupId))
      {
      dictionary.TryAdd(user.GroupId, new HashSet<string>());
      }

      dictionary[user.GroupId].Add(user.Id.ToString());
      }


      Is the act of adding an item into the HashSet inherently thread safe because HashSet is a value property of the concurrent dictionary?







      c# multithreading concurrentdictionary






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 20 at 0:44









      Camilo Terevinto

      17.9k63465




      17.9k63465










      asked Nov 20 at 0:16









      Marko

      7,17752941




      7,17752941
























          3 Answers
          3






          active

          oldest

          votes


















          4














          No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:





          1. Use AddOrUpdate as @TheGeneral mentioned:



            dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());



          2. Use a concurrent collection, like the ConcurrentBag<T>:



            ConcurrentDictionary<int, ConcurrentBag<string>>



          Whenever you are building the Dictionary, as in your code, you should be better off accessing it as little as possible. Think of something like this:



          var dictionary = new ConcurrentDictionary<int, ConcurrentBag<string>>();
          var grouppedUsers = users.GroupBy(u => u.GroupId);

          foreach (var group in grouppedUsers)
          {
          // get the bag from the dictionary or create it if it doesn't exist
          var currentBag = dictionary.GetOrAdd(group.Key, new ConcurrentBag<string>());

          // load it with the users required
          foreach (var user in group)
          {
          if (!currentBag.Contains(user.Id.ToString())
          {
          currentBag.Add(user.Id.ToString());
          }
          }
          }



          1. If you actually want a built-in concurrent HashSet-like collection, you'd need to use ConcurrentDictionary<int, ConcurrentDictionary<string, string>>, and care either about the key or the value from the inner one.






          share|improve this answer























          • Oh now I get the ConcurrentBag comment.
            – Joshua
            Nov 20 at 0:35










          • Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
            – Marko
            Nov 20 at 0:38










          • @Marko No, it behaves more like a concurrent list
            – Camilo Terevinto
            Nov 20 at 0:41










          • @CamiloTerevinto The only problem I see with ConcurrentBag is how can I remove items from the bag? There is no Remove... looks like I need to use TryTake?
            – Marko
            Nov 20 at 1:08





















          5














          No. Putting a container in a thread-safe container does not make the inner container thread safe.



          dictionary[user.GroupId].Add(user.Id.ToString());


          is calling HashSet's add after retrieving it from the ConcurrentDictionary. If this GroupId is looked up from two threads at once this would break your code with strange failure modes. I saw the result of one of my teammates making the mistake of not locking his sets, and it wasn't pretty.



          This is a plausible solution. I'd do something different myself but this is closer to your code.



          if (!dictionary.ContainsKey(user.GroupId)
          {
          dictionary.TryAdd(user.GroupId, new HashSet<string>());
          }
          var groups = dictionary[user.GroupId];
          lock(groups)
          {
          groups.Add(user.Id.ToString())
          }





          share|improve this answer























          • You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
            – TheGeneral
            Nov 20 at 0:34












          • @Joshua Why do you say that you would do something different? What's wrong with locking the hash set like this? Is there a better way to do it?
            – Marko
            Nov 20 at 1:14










          • @Marko At work we have a more powerful primitive to build this from. The locking isn't bad, it's just slightly suboptimal and a lot easier to understand.
            – Joshua
            Nov 20 at 1:23



















          1














          Using a ConcurrentDictionary like this is not thread safe



          dictionary[user.GroupId].Add(user.Id.ToString());


          instead use



          AddOrUpdate(TKey, TValue, Func)



          dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());


          Or as Camilo Terevinto said ConcurrentBag is probably where you want to be






          share|improve this answer





















          • AddOrUpdate should work, but, wouldn't it be better to construct the entire group instead of accessing the dictionary for each user? Also, if it's a variable, and not a class field/property, it shouldn't make a difference, should it?
            – Camilo Terevinto
            Nov 20 at 0:26










          • @CamiloTerevinto yeah you are correct, i ignored all the code. I am a bit busy, if you make an answer ill upvote and remove this
            – TheGeneral
            Nov 20 at 0:27













          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384465%2fis-hashsett-thread-safe-as-a-value-of-concurrentdictionarytkey-hashsett%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          4














          No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:





          1. Use AddOrUpdate as @TheGeneral mentioned:



            dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());



          2. Use a concurrent collection, like the ConcurrentBag<T>:



            ConcurrentDictionary<int, ConcurrentBag<string>>



          Whenever you are building the Dictionary, as in your code, you should be better off accessing it as little as possible. Think of something like this:



          var dictionary = new ConcurrentDictionary<int, ConcurrentBag<string>>();
          var grouppedUsers = users.GroupBy(u => u.GroupId);

          foreach (var group in grouppedUsers)
          {
          // get the bag from the dictionary or create it if it doesn't exist
          var currentBag = dictionary.GetOrAdd(group.Key, new ConcurrentBag<string>());

          // load it with the users required
          foreach (var user in group)
          {
          if (!currentBag.Contains(user.Id.ToString())
          {
          currentBag.Add(user.Id.ToString());
          }
          }
          }



          1. If you actually want a built-in concurrent HashSet-like collection, you'd need to use ConcurrentDictionary<int, ConcurrentDictionary<string, string>>, and care either about the key or the value from the inner one.






          share|improve this answer























          • Oh now I get the ConcurrentBag comment.
            – Joshua
            Nov 20 at 0:35










          • Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
            – Marko
            Nov 20 at 0:38










          • @Marko No, it behaves more like a concurrent list
            – Camilo Terevinto
            Nov 20 at 0:41










          • @CamiloTerevinto The only problem I see with ConcurrentBag is how can I remove items from the bag? There is no Remove... looks like I need to use TryTake?
            – Marko
            Nov 20 at 1:08


















          4














          No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:





          1. Use AddOrUpdate as @TheGeneral mentioned:



            dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());



          2. Use a concurrent collection, like the ConcurrentBag<T>:



            ConcurrentDictionary<int, ConcurrentBag<string>>



          Whenever you are building the Dictionary, as in your code, you should be better off accessing it as little as possible. Think of something like this:



          var dictionary = new ConcurrentDictionary<int, ConcurrentBag<string>>();
          var grouppedUsers = users.GroupBy(u => u.GroupId);

          foreach (var group in grouppedUsers)
          {
          // get the bag from the dictionary or create it if it doesn't exist
          var currentBag = dictionary.GetOrAdd(group.Key, new ConcurrentBag<string>());

          // load it with the users required
          foreach (var user in group)
          {
          if (!currentBag.Contains(user.Id.ToString())
          {
          currentBag.Add(user.Id.ToString());
          }
          }
          }



          1. If you actually want a built-in concurrent HashSet-like collection, you'd need to use ConcurrentDictionary<int, ConcurrentDictionary<string, string>>, and care either about the key or the value from the inner one.






          share|improve this answer























          • Oh now I get the ConcurrentBag comment.
            – Joshua
            Nov 20 at 0:35










          • Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
            – Marko
            Nov 20 at 0:38










          • @Marko No, it behaves more like a concurrent list
            – Camilo Terevinto
            Nov 20 at 0:41










          • @CamiloTerevinto The only problem I see with ConcurrentBag is how can I remove items from the bag? There is no Remove... looks like I need to use TryTake?
            – Marko
            Nov 20 at 1:08
















          4












          4








          4






          No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:





          1. Use AddOrUpdate as @TheGeneral mentioned:



            dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());



          2. Use a concurrent collection, like the ConcurrentBag<T>:



            ConcurrentDictionary<int, ConcurrentBag<string>>



          Whenever you are building the Dictionary, as in your code, you should be better off accessing it as little as possible. Think of something like this:



          var dictionary = new ConcurrentDictionary<int, ConcurrentBag<string>>();
          var grouppedUsers = users.GroupBy(u => u.GroupId);

          foreach (var group in grouppedUsers)
          {
          // get the bag from the dictionary or create it if it doesn't exist
          var currentBag = dictionary.GetOrAdd(group.Key, new ConcurrentBag<string>());

          // load it with the users required
          foreach (var user in group)
          {
          if (!currentBag.Contains(user.Id.ToString())
          {
          currentBag.Add(user.Id.ToString());
          }
          }
          }



          1. If you actually want a built-in concurrent HashSet-like collection, you'd need to use ConcurrentDictionary<int, ConcurrentDictionary<string, string>>, and care either about the key or the value from the inner one.






          share|improve this answer














          No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:





          1. Use AddOrUpdate as @TheGeneral mentioned:



            dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());



          2. Use a concurrent collection, like the ConcurrentBag<T>:



            ConcurrentDictionary<int, ConcurrentBag<string>>



          Whenever you are building the Dictionary, as in your code, you should be better off accessing it as little as possible. Think of something like this:



          var dictionary = new ConcurrentDictionary<int, ConcurrentBag<string>>();
          var grouppedUsers = users.GroupBy(u => u.GroupId);

          foreach (var group in grouppedUsers)
          {
          // get the bag from the dictionary or create it if it doesn't exist
          var currentBag = dictionary.GetOrAdd(group.Key, new ConcurrentBag<string>());

          // load it with the users required
          foreach (var user in group)
          {
          if (!currentBag.Contains(user.Id.ToString())
          {
          currentBag.Add(user.Id.ToString());
          }
          }
          }



          1. If you actually want a built-in concurrent HashSet-like collection, you'd need to use ConcurrentDictionary<int, ConcurrentDictionary<string, string>>, and care either about the key or the value from the inner one.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 20 at 0:41

























          answered Nov 20 at 0:34









          Camilo Terevinto

          17.9k63465




          17.9k63465












          • Oh now I get the ConcurrentBag comment.
            – Joshua
            Nov 20 at 0:35










          • Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
            – Marko
            Nov 20 at 0:38










          • @Marko No, it behaves more like a concurrent list
            – Camilo Terevinto
            Nov 20 at 0:41










          • @CamiloTerevinto The only problem I see with ConcurrentBag is how can I remove items from the bag? There is no Remove... looks like I need to use TryTake?
            – Marko
            Nov 20 at 1:08




















          • Oh now I get the ConcurrentBag comment.
            – Joshua
            Nov 20 at 0:35










          • Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
            – Marko
            Nov 20 at 0:38










          • @Marko No, it behaves more like a concurrent list
            – Camilo Terevinto
            Nov 20 at 0:41










          • @CamiloTerevinto The only problem I see with ConcurrentBag is how can I remove items from the bag? There is no Remove... looks like I need to use TryTake?
            – Marko
            Nov 20 at 1:08


















          Oh now I get the ConcurrentBag comment.
          – Joshua
          Nov 20 at 0:35




          Oh now I get the ConcurrentBag comment.
          – Joshua
          Nov 20 at 0:35












          Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
          – Marko
          Nov 20 at 0:38




          Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
          – Marko
          Nov 20 at 0:38












          @Marko No, it behaves more like a concurrent list
          – Camilo Terevinto
          Nov 20 at 0:41




          @Marko No, it behaves more like a concurrent list
          – Camilo Terevinto
          Nov 20 at 0:41












          @CamiloTerevinto The only problem I see with ConcurrentBag is how can I remove items from the bag? There is no Remove... looks like I need to use TryTake?
          – Marko
          Nov 20 at 1:08






          @CamiloTerevinto The only problem I see with ConcurrentBag is how can I remove items from the bag? There is no Remove... looks like I need to use TryTake?
          – Marko
          Nov 20 at 1:08















          5














          No. Putting a container in a thread-safe container does not make the inner container thread safe.



          dictionary[user.GroupId].Add(user.Id.ToString());


          is calling HashSet's add after retrieving it from the ConcurrentDictionary. If this GroupId is looked up from two threads at once this would break your code with strange failure modes. I saw the result of one of my teammates making the mistake of not locking his sets, and it wasn't pretty.



          This is a plausible solution. I'd do something different myself but this is closer to your code.



          if (!dictionary.ContainsKey(user.GroupId)
          {
          dictionary.TryAdd(user.GroupId, new HashSet<string>());
          }
          var groups = dictionary[user.GroupId];
          lock(groups)
          {
          groups.Add(user.Id.ToString())
          }





          share|improve this answer























          • You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
            – TheGeneral
            Nov 20 at 0:34












          • @Joshua Why do you say that you would do something different? What's wrong with locking the hash set like this? Is there a better way to do it?
            – Marko
            Nov 20 at 1:14










          • @Marko At work we have a more powerful primitive to build this from. The locking isn't bad, it's just slightly suboptimal and a lot easier to understand.
            – Joshua
            Nov 20 at 1:23
















          5














          No. Putting a container in a thread-safe container does not make the inner container thread safe.



          dictionary[user.GroupId].Add(user.Id.ToString());


          is calling HashSet's add after retrieving it from the ConcurrentDictionary. If this GroupId is looked up from two threads at once this would break your code with strange failure modes. I saw the result of one of my teammates making the mistake of not locking his sets, and it wasn't pretty.



          This is a plausible solution. I'd do something different myself but this is closer to your code.



          if (!dictionary.ContainsKey(user.GroupId)
          {
          dictionary.TryAdd(user.GroupId, new HashSet<string>());
          }
          var groups = dictionary[user.GroupId];
          lock(groups)
          {
          groups.Add(user.Id.ToString())
          }





          share|improve this answer























          • You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
            – TheGeneral
            Nov 20 at 0:34












          • @Joshua Why do you say that you would do something different? What's wrong with locking the hash set like this? Is there a better way to do it?
            – Marko
            Nov 20 at 1:14










          • @Marko At work we have a more powerful primitive to build this from. The locking isn't bad, it's just slightly suboptimal and a lot easier to understand.
            – Joshua
            Nov 20 at 1:23














          5












          5








          5






          No. Putting a container in a thread-safe container does not make the inner container thread safe.



          dictionary[user.GroupId].Add(user.Id.ToString());


          is calling HashSet's add after retrieving it from the ConcurrentDictionary. If this GroupId is looked up from two threads at once this would break your code with strange failure modes. I saw the result of one of my teammates making the mistake of not locking his sets, and it wasn't pretty.



          This is a plausible solution. I'd do something different myself but this is closer to your code.



          if (!dictionary.ContainsKey(user.GroupId)
          {
          dictionary.TryAdd(user.GroupId, new HashSet<string>());
          }
          var groups = dictionary[user.GroupId];
          lock(groups)
          {
          groups.Add(user.Id.ToString())
          }





          share|improve this answer














          No. Putting a container in a thread-safe container does not make the inner container thread safe.



          dictionary[user.GroupId].Add(user.Id.ToString());


          is calling HashSet's add after retrieving it from the ConcurrentDictionary. If this GroupId is looked up from two threads at once this would break your code with strange failure modes. I saw the result of one of my teammates making the mistake of not locking his sets, and it wasn't pretty.



          This is a plausible solution. I'd do something different myself but this is closer to your code.



          if (!dictionary.ContainsKey(user.GroupId)
          {
          dictionary.TryAdd(user.GroupId, new HashSet<string>());
          }
          var groups = dictionary[user.GroupId];
          lock(groups)
          {
          groups.Add(user.Id.ToString())
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 20 at 0:34

























          answered Nov 20 at 0:27









          Joshua

          22.9k547100




          22.9k547100












          • You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
            – TheGeneral
            Nov 20 at 0:34












          • @Joshua Why do you say that you would do something different? What's wrong with locking the hash set like this? Is there a better way to do it?
            – Marko
            Nov 20 at 1:14










          • @Marko At work we have a more powerful primitive to build this from. The locking isn't bad, it's just slightly suboptimal and a lot easier to understand.
            – Joshua
            Nov 20 at 1:23


















          • You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
            – TheGeneral
            Nov 20 at 0:34












          • @Joshua Why do you say that you would do something different? What's wrong with locking the hash set like this? Is there a better way to do it?
            – Marko
            Nov 20 at 1:14










          • @Marko At work we have a more powerful primitive to build this from. The locking isn't bad, it's just slightly suboptimal and a lot easier to understand.
            – Joshua
            Nov 20 at 1:23
















          You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
          – TheGeneral
          Nov 20 at 0:34






          You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
          – TheGeneral
          Nov 20 at 0:34














          @Joshua Why do you say that you would do something different? What's wrong with locking the hash set like this? Is there a better way to do it?
          – Marko
          Nov 20 at 1:14




          @Joshua Why do you say that you would do something different? What's wrong with locking the hash set like this? Is there a better way to do it?
          – Marko
          Nov 20 at 1:14












          @Marko At work we have a more powerful primitive to build this from. The locking isn't bad, it's just slightly suboptimal and a lot easier to understand.
          – Joshua
          Nov 20 at 1:23




          @Marko At work we have a more powerful primitive to build this from. The locking isn't bad, it's just slightly suboptimal and a lot easier to understand.
          – Joshua
          Nov 20 at 1:23











          1














          Using a ConcurrentDictionary like this is not thread safe



          dictionary[user.GroupId].Add(user.Id.ToString());


          instead use



          AddOrUpdate(TKey, TValue, Func)



          dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());


          Or as Camilo Terevinto said ConcurrentBag is probably where you want to be






          share|improve this answer





















          • AddOrUpdate should work, but, wouldn't it be better to construct the entire group instead of accessing the dictionary for each user? Also, if it's a variable, and not a class field/property, it shouldn't make a difference, should it?
            – Camilo Terevinto
            Nov 20 at 0:26










          • @CamiloTerevinto yeah you are correct, i ignored all the code. I am a bit busy, if you make an answer ill upvote and remove this
            – TheGeneral
            Nov 20 at 0:27


















          1














          Using a ConcurrentDictionary like this is not thread safe



          dictionary[user.GroupId].Add(user.Id.ToString());


          instead use



          AddOrUpdate(TKey, TValue, Func)



          dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());


          Or as Camilo Terevinto said ConcurrentBag is probably where you want to be






          share|improve this answer





















          • AddOrUpdate should work, but, wouldn't it be better to construct the entire group instead of accessing the dictionary for each user? Also, if it's a variable, and not a class field/property, it shouldn't make a difference, should it?
            – Camilo Terevinto
            Nov 20 at 0:26










          • @CamiloTerevinto yeah you are correct, i ignored all the code. I am a bit busy, if you make an answer ill upvote and remove this
            – TheGeneral
            Nov 20 at 0:27
















          1












          1








          1






          Using a ConcurrentDictionary like this is not thread safe



          dictionary[user.GroupId].Add(user.Id.ToString());


          instead use



          AddOrUpdate(TKey, TValue, Func)



          dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());


          Or as Camilo Terevinto said ConcurrentBag is probably where you want to be






          share|improve this answer












          Using a ConcurrentDictionary like this is not thread safe



          dictionary[user.GroupId].Add(user.Id.ToString());


          instead use



          AddOrUpdate(TKey, TValue, Func)



          dictionary.AddOrUpdate(user.GroupId,  new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());


          Or as Camilo Terevinto said ConcurrentBag is probably where you want to be







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 20 at 0:23









          TheGeneral

          26.7k63163




          26.7k63163












          • AddOrUpdate should work, but, wouldn't it be better to construct the entire group instead of accessing the dictionary for each user? Also, if it's a variable, and not a class field/property, it shouldn't make a difference, should it?
            – Camilo Terevinto
            Nov 20 at 0:26










          • @CamiloTerevinto yeah you are correct, i ignored all the code. I am a bit busy, if you make an answer ill upvote and remove this
            – TheGeneral
            Nov 20 at 0:27




















          • AddOrUpdate should work, but, wouldn't it be better to construct the entire group instead of accessing the dictionary for each user? Also, if it's a variable, and not a class field/property, it shouldn't make a difference, should it?
            – Camilo Terevinto
            Nov 20 at 0:26










          • @CamiloTerevinto yeah you are correct, i ignored all the code. I am a bit busy, if you make an answer ill upvote and remove this
            – TheGeneral
            Nov 20 at 0:27


















          AddOrUpdate should work, but, wouldn't it be better to construct the entire group instead of accessing the dictionary for each user? Also, if it's a variable, and not a class field/property, it shouldn't make a difference, should it?
          – Camilo Terevinto
          Nov 20 at 0:26




          AddOrUpdate should work, but, wouldn't it be better to construct the entire group instead of accessing the dictionary for each user? Also, if it's a variable, and not a class field/property, it shouldn't make a difference, should it?
          – Camilo Terevinto
          Nov 20 at 0:26












          @CamiloTerevinto yeah you are correct, i ignored all the code. I am a bit busy, if you make an answer ill upvote and remove this
          – TheGeneral
          Nov 20 at 0:27






          @CamiloTerevinto yeah you are correct, i ignored all the code. I am a bit busy, if you make an answer ill upvote and remove this
          – TheGeneral
          Nov 20 at 0:27




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53384465%2fis-hashsett-thread-safe-as-a-value-of-concurrentdictionarytkey-hashsett%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          If I really need a card on my start hand, how many mulligans make sense? [duplicate]

          Alcedinidae

          Can an atomic nucleus contain both particles and antiparticles? [duplicate]