ConcurrentDictionary<TKey,TValue>.AddOrUpdate 方法

定義

如果鍵還不存在,則在 中 ConcurrentDictionary<TKey,TValue> 加入一對鍵/值對;如果鍵已經存在,則更新鍵 ConcurrentDictionary<TKey,TValue> 值對。

多載

名稱 Description
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.cs
來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs

使用指定的函式,若鍵尚未存在,則新增鍵值對; 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 如果有金鑰)的結果。

例外狀況

key, , addValueFactoryupdateValueFactorynull

字典包含太多元素。

備註

如果你同時呼叫 AddOrUpdate 不同執行緒, addValueFactory 可能會被呼叫多次,但其鍵值對可能不會每次通話都加入字典。

對於修改與寫入字典的操作,使用 ConcurrentDictionary<TKey,TValue> 細粒度鎖定以確保執行緒安全(字典讀取操作以無鎖方式執行)。 addValueFactoryupdateValueFactory代理可多次執行以驗證值是否如預期新增或更新。 然而,它們會被調用到鎖外,以避免在鎖下執行未知程式碼時可能產生的問題。 因此, AddOrUpdate 對於類別上 ConcurrentDictionary<TKey,TValue> 的所有其他運算,都不是原子的。

另請參閱

適用於

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

來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs

如果鍵尚未存在,則在 中 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

鍵的新值。 如果缺少金鑰,則會是 ,如果金鑰存在則是 的 addValueupdateValueFactory 結果。

例外狀況

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> 細粒度鎖定以確保執行緒安全。 (字典上的讀取操作是以無鎖方式執行。) addValueFactoryupdateValueFactory 代理可多次執行以驗證值是否如預期新增或更新。 然而,它們會被調用到鎖外,以避免在鎖下執行未知程式碼時可能產生的問題。 因此, AddOrUpdate 對於類別上 ConcurrentDictionary<TKey,TValue> 的所有其他運算,都不是原子的。

另請參閱

適用於

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

來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs
來源:
ConcurrentDictionary.cs

使用指定的函式和參數,若鍵尚未存在,則加入鍵值對, 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) where TArg : allows ref struct;
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 中無參考)。

字典包含太多元素。

備註

如果你同時呼叫 AddOrUpdate 不同執行緒, addValueFactory 可能會被呼叫多次,但其鍵值對可能不會每次通話都加入字典。

對於修改及寫入字典的操作,使用 ConcurrentDictionary<TKey,TValue> 細粒度鎖定以確保執行緒安全。 (字典上的讀取操作是以無鎖方式執行。) addValueFactoryupdateValueFactory 代理可多次執行以驗證值是否如預期新增或更新。 然而,它們會被調用到鎖外,以避免在鎖下執行未知程式碼時可能產生的問題。 因此, AddOrUpdate 對於類別上 ConcurrentDictionary<TKey,TValue> 的所有其他運算,都不是原子的。

適用於