Когда. NET TaskCompletionSource Tasks соответствует критериям G C (без root-прав)? - PullRequest
1 голос
/ 27 мая 2020

Я пишу служебный класс для некоторого асинхронного кода, и я хочу убедиться, что я не создаю утечек памяти с дизайном. Предположим, у меня есть код, который выполняется аналогично приведенному ниже классу. (Очевидно, вы не стали бы писать код, который работает так, но у меня есть несколько путей кода, которые все сходятся в единую базовую функцию, и один из этих путей кода эффективно выполняет это). Ключевым моментом в коде является то, что ничто в коде my не содержит ссылки либо на TaskCompletionSource, либо на его Task, хотя NET может делать какое-то колдовство, которое делает root их.

Предположим, что экземпляры Foo создаются по мере необходимости и не имеют постоянного рутирования. tcs.Task рутирован? Что еще более важно, предположим, что request никогда не завершается, поэтому результат не устанавливается. Будет ли tcs.Task торчать вечно? А как насчет задачи продолжения? Или их время жизни зависит от объекта Foo, и они go уйдут, когда экземпляр Foo получит G C -ed?

class Foo
{
    public void Bar(Action<Action<object>> request, Action<T> callback)
    {
        var tcs = new TaskCompletionSource<object>();
        request(result => tcs.SetResult(result));  // this runs asynchronously
        tcs.Task.ContinueWith(task => callback(task.Result));
    }
}

1 Ответ

0 голосов
/ 27 мая 2020

Предположим, что экземпляры Foo создаются по мере необходимости и не имеют постоянного рутирования. Tcs.Task рутирован?

Нет. Нет причин для маршрутизации tcs.Task из Bar и request. Поскольку вы передаете tcs в лямбде, он будет «закрыт», т.е. будет создан объект, и он будет передан как в Bar, так и в request. После завершения обеих подпрограмм tcs.Task станет недоступным и читаемым для сбора.

Что еще более важно, предположим, что запрос никогда не завершается, поэтому результат не устанавливается. Будет ли tcs.Task оставаться там вечно?

Если request никогда не завершается, у вас больше проблем, чем просто tcs.Task. Это означает, что весь поток будет заблокирован и останется активным до конца вашего процесса, со всем его стеком (1 МБ) и всем графом объектов, который укоренен в этом стеке. Ущерб еще больше, если вы также приобретаете неуправляемые ресурсы. Если request завершится ошибкой с исключением, он закончится, его стек будет освобожден, и объекты, которые в нем внедрены, станут читаемыми для сбора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...