ConcurrentDictionary<TKey,TValue>.AddOrUpdate 方法

定义

将键/值对添加到 ConcurrentDictionary<TKey,TValue> 键不存在时,或更新键/值对( ConcurrentDictionary<TKey,TValue> 如果该键已存在)。

重载

名称 说明
AddOrUpdate(TKey, Func<TKey,TValue>, Func<TKey,TValue,TValue>)

使用指定的函数将键/值对添加到 ConcurrentDictionary<TKey,TValue> 键不存在时,或更新键/值对( ConcurrentDictionary<TKey,TValue> 如果键已存在)。

AddOrUpdate(TKey, TValue, Func<TKey,TValue,TValue>)

将键/值对添加到 ConcurrentDictionary<TKey,TValue> 键不存在时,或使用指定函数更新键/值对 ConcurrentDictionary<TKey,TValue> (如果键已存在)。

AddOrUpdate<TArg>(TKey, Func<TKey,TArg,TValue>, Func<TKey,TValue,TArg,TValue>, TArg)

使用指定的函数和参数将键/值对添加到 ConcurrentDictionary<TKey,TValue> 键不存在时,或更新键/值对( ConcurrentDictionary<TKey,TValue> 如果键已存在)。

示例

以下示例演示如何调用 AddOrUpdate 该方法:

class CD_GetOrAddOrUpdate
{
    // Demonstrates:
    //      ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
    //      ConcurrentDictionary<TKey, TValue>.GetOrAdd()
    //      ConcurrentDictionary<TKey, TValue>[]
    static void Main()
    {
        // Construct a ConcurrentDictionary
        ConcurrentDictionary<int, int> cd = new ConcurrentDictionary<int, int>();

        // Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
        Parallel.For(0, 10000, i =>
        {
            // Initial call will set cd[1] = 1.
            // Ensuing calls will set cd[1] = cd[1] + 1
            cd.AddOrUpdate(1, 1, (key, oldValue) => oldValue + 1);
        });

        Console.WriteLine("After 10000 AddOrUpdates, cd[1] = {0}, should be 10000", cd[1]);

        // Should return 100, as key 2 is not yet in the dictionary
        int value = cd.GetOrAdd(2, (key) => 100);
        Console.WriteLine("After initial GetOrAdd, cd[2] = {0} (should be 100)", value);

        // Should return 100, as key 2 is already set to that value
        value = cd.GetOrAdd(2, 10000);
        Console.WriteLine("After second GetOrAdd, cd[2] = {0} (should be 100)", value);
    }
}
// Demonstrates:
//      ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
//      ConcurrentDictionary<TKey, TValue>.GetOrAdd()
//      ConcurrentDictionary<TKey, TValue>[]

// Construct a ConcurrentDictionary
let cd = ConcurrentDictionary<int, int>()

// Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
Parallel.For(
    0,
    10000,
    fun i ->

        // Initial call will set cd[1] = 1.
        // Ensuing calls will set cd[1] = cd[1] + 1
        cd.AddOrUpdate(1, 1, (fun key oldValue -> oldValue + 1)) |> ignore
)
|> ignore

printfn $"After 10000 AddOrUpdates, cd[1] = {cd[1]}, should be 10000"

// Should return 100, as key 2 is not yet in the dictionary
let value = cd.GetOrAdd(2, (fun key -> 100))
printfn $"After initial GetOrAdd, cd[2] = {value} (should be 100)"

// Should return 100, as key 2 is already set to that value2
let value2 = cd.GetOrAdd(2, 10000)
printfn $"After second GetOrAdd, cd[2] = {value2} (should be 100)"
' Imports System.Collections.Concurrent
' Imports System.Threading.Tasks

Class CD_GetOrAddOrUpdate

    ' Demonstrates:
    ' ConcurrentDictionary<TKey, TValue>.AddOrUpdate()
    ' ConcurrentDictionary<TKey, TValue>.GetOrAdd()
    ' ConcurrentDictionary<TKey, TValue>[]
    Shared Sub Main()
        ' Construct a ConcurrentDictionary
        Dim cd As New ConcurrentDictionary(Of Integer, Integer)()

        ' Bombard the ConcurrentDictionary with 10000 competing AddOrUpdates
        Parallel.For(0, 10000,
                       Sub(i)
                           ' Initial call will set cd[1] = 1. 
                           ' Ensuing calls will set cd[1] = cd[1] + 1
                           cd.AddOrUpdate(1, 1, Function(key, oldValue) oldValue + 1)
                       End Sub)

        Console.WriteLine("After 10000 AddOrUpdates, cd[1] = {0}, should be 10000", cd(1))

        ' Should return 100, as key 2 is not yet in the dictionary
        Dim value As Integer = cd.GetOrAdd(2, Function(key) 100)
        Console.WriteLine("After initial GetOrAdd, cd[2] = {0} (should be 100)", value)

        ' Should return 100, as key 2 is already set to that value
        value = cd.GetOrAdd(2, 10000)
        Console.WriteLine("After second GetOrAdd, cd[2] = {0} (should be 100)", value)
    End Sub
End Class

AddOrUpdate(TKey, Func<TKey,TValue>, Func<TKey,TValue,TValue>)

使用指定的函数将键/值对添加到 ConcurrentDictionary<TKey,TValue> 键不存在时,或更新键/值对( ConcurrentDictionary<TKey,TValue> 如果键已存在)。

public:
 TValue AddOrUpdate(TKey key, Func<TKey, TValue> ^ addValueFactory, Func<TKey, TValue, TValue> ^ updateValueFactory);
public TValue AddOrUpdate(TKey key, Func<TKey,TValue> addValueFactory, Func<TKey,TValue,TValue> updateValueFactory);
member this.AddOrUpdate : 'Key * Func<'Key, 'Value> * Func<'Key, 'Value, 'Value> -> 'Value
Public Function AddOrUpdate (key As TKey, addValueFactory As Func(Of TKey, TValue), updateValueFactory As Func(Of TKey, TValue, TValue)) As TValue

参数

key
TKey

要添加的键或应更新其值。

addValueFactory
Func<TKey,TValue>

用于为缺席键生成值的函数。

updateValueFactory
Func<TKey,TValue,TValue>

用于根据键的现有值为现有键生成新值的函数。

返回

TValue

键的新值。 这要么是(如果缺少键)的结果,要么是 addValueFactory (如果存在键)的结果 updateValueFactory

例外

keyaddValueFactoryupdateValueFactorynull

字典包含过多的元素。

注解

如果同时在不同线程上调用 AddOrUpdateaddValueFactory 可以多次调用,但每次调用时,其键/值对可能不会添加到字典中。

对于对字典的修改和写入操作, ConcurrentDictionary<TKey,TValue> 请使用精细锁定来确保线程安全(字典上的读取操作以无锁方式执行)。 addValueFactory可以多次执行和updateValueFactory委托,以验证值是否已按预期添加或更新。 但是,在锁外调用它们,以避免锁下执行未知代码时可能出现的问题。 因此, AddOrUpdate 对于类上 ConcurrentDictionary<TKey,TValue> 所有其他操作,不是原子性的。

另请参阅

适用于

AddOrUpdate(TKey, TValue, Func<TKey,TValue,TValue>)

将键/值对添加到 ConcurrentDictionary<TKey,TValue> 键不存在时,或使用指定函数更新键/值对 ConcurrentDictionary<TKey,TValue> (如果键已存在)。

public:
 TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> ^ updateValueFactory);
public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey,TValue,TValue> updateValueFactory);
member this.AddOrUpdate : 'Key * 'Value * Func<'Key, 'Value, 'Value> -> 'Value
Public Function AddOrUpdate (key As TKey, addValue As TValue, updateValueFactory As Func(Of TKey, TValue, TValue)) As TValue

参数

key
TKey

要添加的键或应更新其值。

addValue
TValue

要为缺席键添加的值。

updateValueFactory
Func<TKey,TValue,TValue>

用于根据键的现有值为现有键生成新值的函数。

返回

TValue

键的新值。 这可以是 addValue (如果密钥不存在)或 updateValueFactory (如果密钥存在)。

例外

keyupdateValueFactorynull.

字典包含过多的元素。

示例

下面的代码示例演示如何初始化 ConcurrentDictionary<TKey,TValue> 以及如何使用 AddOrUpdate 方法将其他项添加到集合,并更新现有项。

using System;
using System.Collections.Concurrent;

class CD_Ctor
{
    // Demonstrates:
    //      ConcurrentDictionary<TKey, TValue> ctor(concurrencyLevel, initialCapacity)
    //      ConcurrentDictionary<TKey, TValue>[TKey]
    static void Main()
    {
        // We know how many items we want to insert into the ConcurrentDictionary.
        // So set the initial capacity to some prime number above that, to ensure that
        // the ConcurrentDictionary does not need to be resized while initializing it.
        int HIGHNUMBER = 64;
        int initialCapacity = 101;

        // The higher the concurrencyLevel, the higher the theoretical number of operations
        // that could be performed concurrently on the ConcurrentDictionary.  However, global
        // operations like resizing the dictionary take longer as the concurrencyLevel rises.
        // For the purposes of this example, we'll compromise at numCores * 2.
        int numProcs = Environment.ProcessorCount;
        int concurrencyLevel = numProcs * 2;

        // Construct the dictionary with the desired concurrencyLevel and initialCapacity
        ConcurrentDictionary<int, int> cd = new ConcurrentDictionary<int, int>(concurrencyLevel, initialCapacity);

        // Initialize the dictionary
        for (int i = 1; i <= HIGHNUMBER; i++) cd[i] = i * i;

        Console.WriteLine("The square of 23 is {0} (should be {1})", cd[23], 23 * 23);

        // Now iterate through, adding one to the end of the list. Existing items should be updated to be divided by their
        // key  and a new item will be added that is the square of its key.
        for (int i = 1; i <= HIGHNUMBER + 1; i++)
          cd.AddOrUpdate(i, i * i, (k,v) => v / i);

        Console.WriteLine("The square root of 529 is {0} (should be {1})", cd[23], 529 / 23);
        Console.WriteLine("The square of 65 is {0} (should be {1})", cd[HIGHNUMBER + 1], ((HIGHNUMBER + 1) * (HIGHNUMBER + 1)));
    }
}
open System
open System.Collections.Concurrent

// Demonstrates:
//      ConcurrentDictionary<TKey, TValue> ctor(concurrencyLevel, initialCapacity)
//      ConcurrentDictionary<TKey, TValue>[TKey]

// We know how many items we want to insert into the ConcurrentDictionary.
// So set the initial capacity to some prime number above that, to ensure that
// the ConcurrentDictionary does not need to be resized while initializing it.
let HIGHNUMBER = 64
let initialCapacity = 101

// The higher the concurrencyLevel, the higher the theoretical number of operations
// that could be performed concurrently on the ConcurrentDictionary.  However, global
// operations like resizing the dictionary take longer as the concurrencyLevel rises.
// For the purposes of this example, we'll compromise at numCores * 2.
let numProcs = Environment.ProcessorCount
let concurrencyLevel = numProcs * 2

// Construct the dictionary with the desired concurrencyLevel and initialCapacity
let cd = ConcurrentDictionary<int, int>(concurrencyLevel, initialCapacity)

// Initialize the dictionary
for i = 1 to HIGHNUMBER do
    cd[i] <- i * i

printfn $"The square of 23 is {cd[23]} (should be {23 * 23})"

// Now iterate through, adding one to the end of the list. Existing items should be updated to be divided by their
// key  and a new item will be added that is the square of its key.
for i = 1 to HIGHNUMBER + 1 do
    cd.AddOrUpdate(i, i * i, (fun k v -> v / i)) |> ignore

printfn $"The square root of 529 is {cd[23]} (should be {529 / 23})"
printfn $"The square of 65 is {cd[HIGHNUMBER + 1]} (should be {(HIGHNUMBER + 1) * (HIGHNUMBER + 1)})"
Imports System.Collections.Concurrent

Class CD_Ctor
    ' Demonstrates: 
    '      ConcurrentDictionary<TKey, TValue> ctor(concurrencyLevel, initialCapacity) 
    '      ConcurrentDictionary<TKey, TValue>[TKey] 
    Public Shared Sub Main()
        ' We know how many items we want to insert into the ConcurrentDictionary. 
        ' So set the initial capacity to some prime number above that, to ensure that 
        ' the ConcurrentDictionary does not need to be resized while initializing it. 
        Dim HIGHNUMBER As Integer = 64
        Dim initialCapacity As Integer = 101

        ' The higher the concurrencyLevel, the higher the theoretical number of operations 
        ' that could be performed concurrently on the ConcurrentDictionary.  However, global 
        ' operations like resizing the dictionary take longer as the concurrencyLevel rises.  
        ' For the purposes of this example, we'll compromise at numCores * 2. 
        Dim numProcs As Integer = Environment.ProcessorCount
        Dim concurrencyLevel As Integer = numProcs * 2

        ' Construct the dictionary with the desired concurrencyLevel and initialCapacity
        Dim cd As New ConcurrentDictionary(Of Integer, Integer)(concurrencyLevel, initialCapacity)

        ' Initialize the dictionary 
        For i As Integer = 1 To HIGHNUMBER
            cd(i) = i * i
        Next

        Console.WriteLine("The square of 23 is {0} (should be {1})", cd(23), 23 * 23)

        ' Now iterate through, adding one to the end of the list. Existing items should be updated to be divided by their 
        ' key  and a new item will be added that is the square of its key.
        For i As Integer = 1 To HIGHNUMBER + 1

            cd.AddOrUpdate(i, i * i, Function(k, v)
                                         Return v / i
                                     End Function)
        Next

        Console.WriteLine("The square root of 529 is {0} (should be {1})", cd(23), 529 / 23)
        Console.WriteLine("The square of 65 is {0} (should be {1})", cd(HIGHNUMBER + 1), ((HIGHNUMBER + 1) * (HIGHNUMBER + 1)))

    End Sub
End Class

对于对字典的修改和写入操作, ConcurrentDictionary<TKey,TValue> 请使用精细锁定来确保线程安全。 (字典上的读取操作以无锁方式执行。 addValueFactory 可以多次执行和 updateValueFactory 委托,以验证值是否已按预期添加或更新。 但是,在锁外调用它们,以避免锁下执行未知代码时可能出现的问题。 因此, AddOrUpdate 对于类上 ConcurrentDictionary<TKey,TValue> 所有其他操作,不是原子性的。

另请参阅

适用于

AddOrUpdate<TArg>(TKey, Func<TKey,TArg,TValue>, Func<TKey,TValue,TArg,TValue>, TArg)

使用指定的函数和参数将键/值对添加到 ConcurrentDictionary<TKey,TValue> 键不存在时,或更新键/值对( ConcurrentDictionary<TKey,TValue> 如果键已存在)。

public:
generic <typename TArg>
 TValue AddOrUpdate(TKey key, Func<TKey, TArg, TValue> ^ addValueFactory, Func<TKey, TValue, TArg, TValue> ^ updateValueFactory, TArg factoryArgument);
public TValue AddOrUpdate<TArg>(TKey key, Func<TKey,TArg,TValue> addValueFactory, Func<TKey,TValue,TArg,TValue> updateValueFactory, TArg factoryArgument);
member this.AddOrUpdate : 'Key * Func<'Key, 'Arg, 'Value> * Func<'Key, 'Value, 'Arg, 'Value> * 'Arg -> 'Value
Public Function AddOrUpdate(Of TArg) (key As TKey, addValueFactory As Func(Of TKey, TArg, TValue), updateValueFactory As Func(Of TKey, TValue, TArg, TValue), factoryArgument As TArg) As TValue

类型参数

TArg

要传入 addValueFactoryupdateValueFactory传递的参数的类型。

参数

key
TKey

要添加的键或应更新其值。

addValueFactory
Func<TKey,TArg,TValue>

用于为缺席键生成值的函数。

updateValueFactory
Func<TKey,TValue,TArg,TValue>

用于根据键的现有值为现有键生成新值的函数。

factoryArgument
TArg

要传入 addValueFactory 和传入的参数 updateValueFactory

返回

TValue

键的新值。 这要么是(如果缺少键)的结果,要么是 addValueFactory (如果存在键)的结果 updateValueFactory

例外

keyaddValueFactoryupdateValueFactory 为空引用(Visual Basic 中无任何内容)。

字典包含过多的元素。

注解

如果同时在不同线程上调用 AddOrUpdateaddValueFactory 可以多次调用,但每次调用时,其键/值对可能不会添加到字典中。

对于对字典的修改和写入操作, ConcurrentDictionary<TKey,TValue> 请使用精细锁定来确保线程安全。 (字典上的读取操作以无锁方式执行。 addValueFactory 可以多次执行和 updateValueFactory 委托,以验证值是否已按预期添加或更新。 但是,在锁外调用它们,以避免锁下执行未知代码时可能出现的问题。 因此, AddOrUpdate 对于类上 ConcurrentDictionary<TKey,TValue> 所有其他操作,不是原子性的。

适用于