什麼是 ReaderWriterLockSlim

ReaderWriterLockSlim 是 .NET Framework 提供的一種同步機制,用於管理對共享資源的訪問。它允許多個讀取者同時訪問資源,但只允許一個寫入者訪問資源。這有助於提高效能,特別是當有大量讀取操作時。

在這段程式碼中,ReaderWriterLockSlim 用於控制對 actionQueue 佇列的訪問。它確保在寫入(新增動作)時,不會有其他執行緒正在讀取或寫入。同時,在讀取(執行動作)時,其他執行緒可以繼續讀取,但不允許進行寫入。

另外,ReaderWriterLockSlim 實現了 IDisposable 介面,這意味著它具有釋放資源的能力。

在Unity中使用一個 MonoBehaviour, Singleten, DontDestroyOnLoad 的static Instance,來 管理多線呈 的 回調Action 的 執行順序,確保每一次Unity Update更新只跑一個回調。

在程式碼的 OnDestroy 方法中,lockSlim.Dispose() 被呼叫,這用於釋放 ReaderWriterLockSlim 所佔用的資源,以避免資源洩漏或占用過多的記憶體。

這個技術用在多人聯機的Server更新部分。

private ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();
private Queue<Action> actionQueue = new Queue<Action>();
internal Action SyncCallback( Action listener ) {
	return () => EnqueueAction( () => listener.Invoke() );
}

internal Action<object> SyncCallback( Action<object> listener ) {
	return ( object obj ) => EnqueueAction( () => listener.Invoke( obj ) );
}

internal Action<User> SyncCallback( Action<User> listener ) {
	return ( User user ) => EnqueueAction( () => listener.Invoke( user ) );
}
internal Action<string, object> SyncCallback( Action<string, object> listener ) {
	return ( string eventName, object obj ) => EnqueueAction( () => listener.Invoke( eventName, obj ) );
}

internal Action<string, object[]> SyncCallback( Action<string, object[]> listener ) {
	return ( string eventName, object[] args ) => EnqueueAction( () => listener.Invoke( eventName, args ) );
}

internal Action<T1> SyncCallback<T1>( Action<T1> listener ) {
	return ( T1 arg1 ) => EnqueueAction( () => listener.Invoke( arg1 ) );
}

internal Action<T1, T2> SyncCallback<T1, T2>( Action<T1, T2> listener ) {
	return ( T1 arg1, T2 arg2 ) => EnqueueAction( () => listener.Invoke( arg1, arg2 ) );
}

internal Action<T1, T2, T3> SyncCallback<T1, T2, T3>( Action<T1, T2, T3> listener ) {
	return ( T1 arg1, T2 arg2, T3 arg3 ) => EnqueueAction( () => listener.Invoke( arg1, arg2, arg3 ) );
}

internal Action<T1, T2, T3, T4> SyncCallback<T1, T2, T3, T4>( Action<T1, T2, T3, T4> listener ) {
	return ( T1 arg1, T2 arg2, T3 arg3, T4 arg4 ) => EnqueueAction( () => listener.Invoke( arg1, arg2, arg3, arg4 ) );
}

internal Action<T1, T2, T3, T4, T5> SyncCallback<T1, T2, T3, T4, T5>( Action<T1, T2, T3, T4, T5> listener ) {
	return ( T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5 ) => EnqueueAction( () => listener.Invoke( arg1, arg2, arg3, arg4, arg5 ) );
}
private void EnqueueAction( Action action ) {
	try {
		lockSlim.EnterWriteLock();
		actionQueue.Enqueue( action );
	}
	finally {
		lockSlim.ExitWriteLock();
	}
}
private void OnDestroy() {
	lockSlim.Dispose();
}