© 2026 Hedgehog Software, LLC

TwitterGitHubDiscord
More
CommunitiesDocsAboutTermsPrivacy
Search
Star
Setup for Free
C#C
C#•10mo ago•
31 replies
AllMight

Thread safety when mutating an object

I have two IAsyncEnumerables I want to join into one dictionary of result objects without buffering them into memory - which means build the results objects as they come from the IAsyncEnumerable.
Will this be thread safe and work correctly or do I need to ensure better thread safety?
public class Result
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public record NameResult(string Id, string Name);
public record AgeResult(string Id, int Age);

public class Service
{
    public async Task<IDictionary<string, Result>> ProcessAsync(
        IAsyncEnumerable<NameResult> namesSource, 
        IAsyncEnumerable<AgeResult> agesSource)
    {
        var results = new ConcurrentDictionary<string, Result>();

        async Task ConsumeNamesSource()
        {
            await foreach (NameResult nameResult in namesSource)
            {
                var result = results.GetOrAdd(nameResult.Id, _ => new Result { Name = nameResult.Name });
                result.Name = nameResult.Name;
            }
        }

        async Task ConsumeAgesSource()
        {
            await foreach (AgeResult ageResult in agesSource)
            {
                var result = results.GetOrAdd(ageResult.Id, _ => new Result { Age = ageResult.Age });
                result.Age = ageResult.Age;
            }
        }

        Task namesConsumer = ConsumeNamesSource();
        Task agesConsumer = ConsumeAgesSource();

        await namesConsumer;
        await agesConsumer;

        return results;
    }
}
public class Result
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public record NameResult(string Id, string Name);
public record AgeResult(string Id, int Age);

public class Service
{
    public async Task<IDictionary<string, Result>> ProcessAsync(
        IAsyncEnumerable<NameResult> namesSource, 
        IAsyncEnumerable<AgeResult> agesSource)
    {
        var results = new ConcurrentDictionary<string, Result>();

        async Task ConsumeNamesSource()
        {
            await foreach (NameResult nameResult in namesSource)
            {
                var result = results.GetOrAdd(nameResult.Id, _ => new Result { Name = nameResult.Name });
                result.Name = nameResult.Name;
            }
        }

        async Task ConsumeAgesSource()
        {
            await foreach (AgeResult ageResult in agesSource)
            {
                var result = results.GetOrAdd(ageResult.Id, _ => new Result { Age = ageResult.Age });
                result.Age = ageResult.Age;
            }
        }

        Task namesConsumer = ConsumeNamesSource();
        Task agesConsumer = ConsumeAgesSource();

        await namesConsumer;
        await agesConsumer;

        return results;
    }
}
C# banner
C#Join
We are a programming server aimed at coders discussing everything related to C# (CSharp) and .NET.
61,871Members
Resources

Similar Threads

Was this page helpful?
Recent Announcements

Similar Threads

Question regarding thread safety
C#CC# / help
2y ago
❔ Initializing an object
C#CC# / help
3y ago
Object reference set to an instance of an object.
C#CC# / help
3y ago
✅ Object reference not set to an instance of an object.
C#CC# / help
10mo ago