Информация об изменениях

Сообщение Re[6]: .net core и async lock от 12.04.2021 16:13

Изменено 13.04.2021 1:03 vdimas

Re[6]: .net core и async lock
Здравствуйте, artelk, Вы писали:

V>>SemaphoreSlim имеет унутре очередь ожидающих "потоков" (т.е. задач), но эта очередь организована через прокси-задачи.

V>>Т.е. каждый вызов WaitAsync создаёт и регистрирует еще один объект Task, что считается тяжеловесным для такой операции.
A>Не каждый. Если семафор свободен, возвращается переиспользуемый s_trueTask.

Если семафор свободен, то никакой s_trueTask не требуется.
Собсно, ValueTask изначально планировался как объединение {task, value} для случая, когда асинхронная операция закончилась синхронно, т.е. можно сразу использовать результат. IValueTaskSource появился в результате развития функциональности ValueTask для целей сетевого IO, судя по динамике изменениям исходников в те годы.


A>А если занят, то полюбому же придется создавать какой-то новый task-like объект в куче и возвращать его (завернутым в ValueTask и т.п.).


Если занят, то в https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.inotifycompletion.oncompleted подаётся делегат-продолжение, который можно вызвать, когда у семафора освободится ресурс.

Собсно, подаваемый делегат — это уже Task-like объект.


A>Если ты что-то другое имел ввиду, просьба развернуть.


Имел ввиду хранить эти уже поданные делегаты в очереди и к ним признак захвата контекста.
Вернее, тут нужен не сам признак, а уже захваченный контекст (при надобности).

Ну и, чтобы не писать постоянно ConfigureAwait(false), я бы в конструктор такого семафора добавил аргумент дефолтного поведения, чтобы получить наиболее простой основной сценарий, например:
public class AsyncSemaphore {
    public AsyncSemaphore(int initialCount, bool defaultContinueOnCapturedContext) {

    ...
}

class Foo {

    AsyncSemaphore _sema = new AsyncSemaphore(N, false);

    ...

    async void Bar() {
        using(await _sema) {
            // do smth with a resource
            ...
        }
    }
}
Re[6]: .net core и async lock
Здравствуйте, artelk, Вы писали:

V>>SemaphoreSlim имеет унутре очередь ожидающих "потоков" (т.е. задач), но эта очередь организована через прокси-задачи.

V>>Т.е. каждый вызов WaitAsync создаёт и регистрирует еще один объект Task, что считается тяжеловесным для такой операции.
A>Не каждый. Если семафор свободен, возвращается переиспользуемый s_trueTask.

Если семафор свободен, то никакой s_trueTask не требуется.
Собсно, ValueTask изначально планировался как объединение {task, value} для случая, когда асинхронная операция закончилась синхронно, т.е. можно сразу использовать результат. IValueTaskSource появился в результате развития функциональности ValueTask для целей сетевого IO, судя по динамике изменений исходников в те годы.


A>А если занят, то полюбому же придется создавать какой-то новый task-like объект в куче и возвращать его (завернутым в ValueTask и т.п.).


Если занят, то в https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.inotifycompletion.oncompleted подаётся делегат-продолжение, который можно вызвать, когда у семафора освободится ресурс.

Собсно, подаваемый делегат — это уже Task-like объект.


A>Если ты что-то другое имел ввиду, просьба развернуть.


Имел ввиду хранить эти уже поданные делегаты в очереди и к ним признак захвата контекста.
Вернее, тут нужен не сам признак, а уже захваченный контекст (при надобности).

Ну и, чтобы не писать постоянно ConfigureAwait(false), я бы в конструктор такого семафора добавил аргумент дефолтного поведения, чтобы получить наиболее простой основной сценарий, например:
public class AsyncSemaphore {
    public AsyncSemaphore(int initialCount, bool defaultContinueOnCapturedContext) {

    ...
}

class Foo {

    AsyncSemaphore _sema = new AsyncSemaphore(N, false);

    ...

    async void Bar() {
        using(await _sema) {
            // do smth with a resource
            ...
        }
    }
}