Синхронизация потоков в приложении с асинхронным кодом
Искал удобный вариант обертывания семафора для создания простого примитива синхронизации, который можно использовать вместе с async/wait. Сделал вариант с использованием ключевого слова using:
public class AsyncLock:Idisposable
{
private readonly SemaphoreSlim _semaphore;
public AsyncLock()
{
_semaphore = new SemaphoreSlim (1,1);
}
public async Task<IDisposable> LockAsync()
{
await _semaphore.WaitAsync().ConfigureAwait(false);
return this;
}
public void Dispose()
{
_semaphore.Release();
}
}
Использую так:
var locker=new AsyncLock();
using(await locker.LockAsync())
{
//Некоторая операция, требующая синхронизации
}
Подскажите пожалуйста, если я AsyncLock использую как член класса, иными словами - многократно в рамках какого-либо модуля, автоматический вызов Dispose может привести к зачистке ресурсов - уничтожению AsyncLock экземпляра, что, само собой, приведет к null-reference исключению?
Ответы (1 шт):
Вызов Dispose не приводит к удалению объекта, если у вас AsyncLock будет объявлен как член класса, например:
class Parent
{
private AsyncLock locker;
// ...
public async Task<int> Bar()
{
using(await locker.LockAsync())
{
//Некоторая операция, требующая синхронизации
}
// тут locker удален из памяти не будет
}
}
то он тудет оставаться в памяни (!= null) до тех пор, пока родительский обхект не будет удален (или явно присвоено null), т.к. на него все равно остается ссылка и GC его не удалит.