Что Стивен Toub означает по
не используют Task.Run в реализации метода; вместо того, чтобы использовать Task.Run для вызова метода
, что вы не должны использовать Task.Run
, чтобы скрыть ЦП работу за методами асинхронными (Task
методы, возвращающие). Если вам нужно обернуть внешний код, скройте его за интерфейсом, который отражает то, что делает этот код. Любой асинхронный ввод-вывод может (и должен) отображаться как возвращаемые методы Task
, а работа с привязкой к ЦП должна быть открыта с помощью соответствующего API. Пусть потребители вашего кода сами решат, как использовать этот код. Когда вы тоже пользуетесь потребителем, используйте Task.Run
для запуска вашего синхронного кода (теперь завернутый и открытый через интерфейс) , где очень ясно, что вы выгружаете работу с привязкой к процессору. Например, в приложениях пользовательского интерфейса вы должны называть Task.Run
на вашем уровне пользовательского интерфейса (и не глубоко в ваших BL или даже DA-слоях), где очень ясно, что пользовательский интерфейс разгружает работу с некоторыми процессорами.
Почему вы думаете, что я не должна вызывать Task.Run в BL? Что делать, если у меня есть ViewModel, который ссылается на сервисный уровень BL и BL (в моем случае это оболочка).
Я думаю, что подпись метода должна точно отражать то, что делает этот метод. Лучшее, что я могу сделать, это перенаправить вас обратно Cleary's article:
Когда разработчик видит два метода в качестве API winrtLibrary.Login() и winrtLibrary.LoginAsync(), конвенции является то, что они представляют собой естественно -асинхронный работа. Другими словами, разработчик ожидает, что winrtLibrary.LoginAsync() будет «естественной» реализацией и что winrtLibrary.Login() по существу представляет собой синхронный (блокирующий) эквивалент этой операции . Этот API подразумевает , что winrtLibrary.Login в какой-то момент будет иметь вызывающий поток в состоянии ожидания , поскольку он блокирует естественно-асинхронную операцию до .
Вы по-прежнему можете скрывать синхронный код за методом асинхронного вызова и следовать правилу Клири, если вы подписываете свой метод как public Task OffloadLoginToTheThreadPool()
. Но я думаю (и, по-видимому, Клири тоже), что альтернатива простому вызову Task.Run
из пользовательского интерфейса (или контроллера) - гораздо лучший подход, и он следует принципам Clean Code.
Что делает этот метод? Что-то долгое, что блокирует ваш интерфейс? Тогда ответ «да», запустите его в новой задаче. –
Да, метод входа может быть длинным.Это зависит от сети и т. Д. Если я блокирую пользовательский интерфейс, я не могу отменить процесс входа в систему. – JuP
Точка, которую сделал Стивен Клири, заключается в том, что 'Task.Run'« уничтожает »Thread для выполнения работы, а Threads - дорого. Однако ваша библиотека C++ НЕОБХОДИМА для работы Thread. Поэтому проблема заключается не столько в том, что «Task.Run» является злом. Но 'Task.Run' обычно скрывает проблему использования потоков. – Aron