Is HashSet thread safe as a value of ConcurrentDictionary<TKey, HashSet>?
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
add a comment |
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
add a comment |
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
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
c# multithreading concurrentdictionary
edited Nov 20 '18 at 0:44
Camilo Terevinto
18.4k63666
18.4k63666
asked Nov 20 '18 at 0:16
MarkoMarko
7,23453041
7,23453041
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:
Use
AddOrUpdate
as @TheGeneral mentioned:
dictionary.AddOrUpdate(user.GroupId, new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());
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());
}
}
}
- 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.
Oh now I get the ConcurrentBag comment.
– Joshua
Nov 20 '18 at 0:35
Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
– Marko
Nov 20 '18 at 0:38
@Marko No, it behaves more like a concurrent list
– Camilo Terevinto
Nov 20 '18 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 '18 at 1:08
add a comment |
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())
}
You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
– Michael Randall
Nov 20 '18 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 '18 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 '18 at 1:23
add a comment |
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
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 '18 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
– Michael Randall
Nov 20 '18 at 0:27
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:
Use
AddOrUpdate
as @TheGeneral mentioned:
dictionary.AddOrUpdate(user.GroupId, new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());
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());
}
}
}
- 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.
Oh now I get the ConcurrentBag comment.
– Joshua
Nov 20 '18 at 0:35
Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
– Marko
Nov 20 '18 at 0:38
@Marko No, it behaves more like a concurrent list
– Camilo Terevinto
Nov 20 '18 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 '18 at 1:08
add a comment |
No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:
Use
AddOrUpdate
as @TheGeneral mentioned:
dictionary.AddOrUpdate(user.GroupId, new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());
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());
}
}
}
- 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.
Oh now I get the ConcurrentBag comment.
– Joshua
Nov 20 '18 at 0:35
Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
– Marko
Nov 20 '18 at 0:38
@Marko No, it behaves more like a concurrent list
– Camilo Terevinto
Nov 20 '18 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 '18 at 1:08
add a comment |
No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:
Use
AddOrUpdate
as @TheGeneral mentioned:
dictionary.AddOrUpdate(user.GroupId, new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());
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());
}
}
}
- 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.
No, the collection (the dictionary itself) is thread-safe, not whatever you put in it. You have a couple of options:
Use
AddOrUpdate
as @TheGeneral mentioned:
dictionary.AddOrUpdate(user.GroupId, new HashSet<string>(), (k,v) => v.Add(user.Id.ToString());
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());
}
}
}
- 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.
edited Nov 20 '18 at 0:41
answered Nov 20 '18 at 0:34
Camilo TerevintoCamilo Terevinto
18.4k63666
18.4k63666
Oh now I get the ConcurrentBag comment.
– Joshua
Nov 20 '18 at 0:35
Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
– Marko
Nov 20 '18 at 0:38
@Marko No, it behaves more like a concurrent list
– Camilo Terevinto
Nov 20 '18 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 '18 at 1:08
add a comment |
Oh now I get the ConcurrentBag comment.
– Joshua
Nov 20 '18 at 0:35
Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
– Marko
Nov 20 '18 at 0:38
@Marko No, it behaves more like a concurrent list
– Camilo Terevinto
Nov 20 '18 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 '18 at 1:08
Oh now I get the ConcurrentBag comment.
– Joshua
Nov 20 '18 at 0:35
Oh now I get the ConcurrentBag comment.
– Joshua
Nov 20 '18 at 0:35
Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
– Marko
Nov 20 '18 at 0:38
Does ConcurrentBag behave as HashSet in other words it does not allow for duplicates in the list?
– Marko
Nov 20 '18 at 0:38
@Marko No, it behaves more like a concurrent list
– Camilo Terevinto
Nov 20 '18 at 0:41
@Marko No, it behaves more like a concurrent list
– Camilo Terevinto
Nov 20 '18 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 '18 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 '18 at 1:08
add a comment |
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())
}
You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
– Michael Randall
Nov 20 '18 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 '18 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 '18 at 1:23
add a comment |
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())
}
You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
– Michael Randall
Nov 20 '18 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 '18 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 '18 at 1:23
add a comment |
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())
}
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())
}
edited Nov 20 '18 at 0:34
answered Nov 20 '18 at 0:27
JoshuaJoshua
23k548101
23k548101
You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
– Michael Randall
Nov 20 '18 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 '18 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 '18 at 1:23
add a comment |
You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
– Michael Randall
Nov 20 '18 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 '18 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 '18 at 1:23
You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
– Michael Randall
Nov 20 '18 at 0:34
You are correct, however exclusively using the func methods will, though i think there are better solutions to this problem
– Michael Randall
Nov 20 '18 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 '18 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 '18 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 '18 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 '18 at 1:23
add a comment |
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
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 '18 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
– Michael Randall
Nov 20 '18 at 0:27
add a comment |
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
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 '18 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
– Michael Randall
Nov 20 '18 at 0:27
add a comment |
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
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
answered Nov 20 '18 at 0:23
Michael RandallMichael Randall
30.6k63465
30.6k63465
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 '18 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
– Michael Randall
Nov 20 '18 at 0:27
add a comment |
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 '18 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
– Michael Randall
Nov 20 '18 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 '18 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 '18 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
– Michael Randall
Nov 20 '18 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
– Michael Randall
Nov 20 '18 at 0:27
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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