Сообщение 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), я бы в конструктор такого семафора добавил аргумент дефолтного поведения, чтобы получить наиболее простой основной сценарий, например:
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), я бы в конструктор такого семафора добавил аргумент дефолтного поведения, чтобы получить наиболее простой основной сценарий, например:
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
...
}
}
}