在 C# 中,共享數據通常意味著在多執行緒環境中,或者在多個類、物件或元件之間共享和存取相同的數據。C# 提供了多種方法來實作數據的共享,每種方法都有其適用場景和優缺點。下面我們將探討一些常見的共享數據方式。
靜態成員
靜態成員(包括靜態欄位、靜態內容和靜態方法)屬於類本身,而不是類的任何特定例項。因此,所有例項都可以存取和修改靜態成員,從而實作數據共享。
public classSharedData
{
publicstaticint SharedValue = 0;
publicstaticvoidIncrementValue()
{
SharedValue++;
}
}
// 在其他類或方法中存取和修改
SharedData.SharedValue = 42;
SharedData.IncrementValue();
註意 :對靜態成員的並行存取必須同步,以防止數據競爭和不一致。
單例模式
單例模式確保一個類只有一個例項,並提供一個全域存取點來存取該例項。這可以用於共享數據,因為所有數據都儲存在這個唯一的例項中。
public classSingleton
{
privatestatic Singleton _instance;
privateSingleton() {}
publicstatic Singleton Instance
{
get
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
}
publicint SharedValue { get; set; }
}
// 使用單例來存取和修改共享數據
Singleton.Instance.SharedValue = 100;
註意 :同樣需要確保對單例例項的並行存取是同步的。
依賴註入(DI)
依賴註入是一種使物件能夠接收它執行所需的其他物件的方式。透過依賴註入,可以輕松地管理和共享數據,尤其是當數據透過服務或倉儲等元件進行封裝時。
publicinterfaceISharedDataService
{
int SharedValue { get; set; }
}
public classSharedDataService : ISharedDataService
{
publicint SharedValue { get; set; }
}
// 在應用程式的某個部份註入共享數據服務
public classSomeComponent
{
privatereadonly ISharedDataService _sharedDataService;
publicSomeComponent(ISharedDataService sharedDataService)
{
_sharedDataService = sharedDataService;
}
publicvoidDoSomething()
{
intvalue = _sharedDataService.SharedValue;
// ...
}
}
// 在應用程式啟動時配置依賴註入容器
註意 :依賴註入容器負責確保所有需要的元件都接收到相同的例項。
跨執行緒共享數據
在多執行緒應用程式中,共享數據通常透過執行緒安全的數據結構或同步機制(如鎖、號誌等)來存取。
privatereadonlyobject _lock = newobject();
privateint _sharedValue;
publicint SharedValue
{
get
{
lock (_lock)
{
return _sharedValue;
}
}
set
{
lock (_lock)
{
_sharedValue = value;
}
}
}
註意 :同步機制可能會影響效能,因此需要仔細選擇和設計。
並行集合
C# 提供了多種執行緒安全的集合類,如
ConcurrentBag<T>
、
ConcurrentDictionary<TKey, TValue>
、
ConcurrentQueue<T>
和
ConcurrentStack<T>
,這些可以用於在多個執行緒之間安全地共享和存取數據。
var bag = new ConcurrentBag<int>();
// 在一個執行緒中添加數據
bag.Add(42);
// 在另一個執行緒中嘗試獲取數據
if (bag.TryTake(outint result))
{
// 處理結果
}
註意 :並行集合通常用於生產者-消費者場景,其中多個執行緒可能同時添加或移除數據。
記憶體對映檔
對於需要在不同行程間共享數據的情況,可以使用記憶體對映檔。記憶體對映檔允許一個行程將其檔內容對映到其地址空間中,而其他行程可以存取同一檔對映的檢視。
using System.IO.MemoryMappedFiles;
// 建立或開啟記憶體對映檔
var mmf = MemoryMappedFile.CreateFromFile("sharedfile.map", FileMode.Create, null, 1024 * 1024, MemoryMappedFileAccess