How can I add or update this .NET collection during Parallel.ForEach?

I have a list of files where each file contains a list of Foodata. Now the same piece of Foo data (for example, Id = 1) can exist in several files, but a later part of the data will overwrite the existing one.

I just read every piece of data in a memory collection.

if !cache.HasKey(foo.Id) then Add    
else cache[foo.Id].UpdatedOn < foo.UpdatedOn then Update  
else do nothing

When I read files (because there are several of them), I also use Parallel.ForEach(files, file => { .. });

I am not sure how I do it.

I was thinking about using ConcurrentDictionary, but I was not sure how to do AddOrUpdatewith the where thing clause.

Any suggestions?

+3
source share
2 answers

ConcurrentDictionary, :

dictionary.AddOrUpdate(foo.Id, foo, (id, existing) => 
    existing.UpdatedOn < foo.UpdatedOn ? foo : existing);

, . MSDN , , , :

, , GetOrAdd, , valueFactory.

, , , , . AddOrUpdate . :

do { 
   while (!TryGetValue(key, out value))
       if (TryAdd(key, addValue)) return;
   newValue = updateValueFactory(key, value);
} while (TryUpdate(key, newValue, value));

TryUpdate , , , , . , , TryGetValue , factory ..

, , factory , .

+4

ConcurrentDictionary.AddOrUpdate:

class Program
{
    static void Main( string[] args )
    {
        var cd = new System.Collections.Concurrent.ConcurrentDictionary<int, int>();

        var a = 0;
        var b = 1;
        var c = 2;

        cd[ 1 ] = a;

        Task.WaitAll(
            Task.Factory.StartNew( () => cd.AddOrUpdate( 1, b, ( key, existingValue ) =>
                {
                    Console.WriteLine( "b" );
                    if( existingValue < b )
                    {
                        Console.WriteLine( "b update" );
                        System.Threading.Thread.Sleep( 2000 );
                        return b;
                    }
                    else
                    {
                        Console.WriteLine( "b no change" );
                        return existingValue;
                    }
                } ) ),

            Task.Factory.StartNew( () => cd.AddOrUpdate( 1, c, ( key, existingValue ) =>
            {
                Console.WriteLine( "c start" );
                if( existingValue < c )
                {
                    Console.WriteLine( "c update" );
                    return c;
                }
                else
                {
                    Console.WriteLine( "c no change" );
                    return existingValue;
                }
            } ) ) );

        Console.WriteLine( "Value: {0}", cd[ 1 ] );

        var input = Console.ReadLine();
    }
}

:

ConcurrentDictionary.AddOrUpdate Test Output

0

All Articles