Запуск дорогостоящей операции в фоновом режиме, не ожидая результата

Я провел исследование по этой теме, но до сих пор не до конца понимаю блоки async и await в C#, поскольку многие люди предлагают разные функции и подходы. Тем не менее, я не могу найти ничего близкого к моей цели.

Я работаю в Unity и хочу отправить несколько снимков экрана через сокет в другое приложение. Unity требует, чтобы снимок экрана был сделан основным потоком, поскольку он не является потокобезопасным. Дорогостоящей операцией является отправка кадра, которую, по моему мнению, лучше обрабатывать фоновым потоком. Это делается в цикле while(running).

Возможно, самый простой способ — просто создать новый поток и передать туда кадр для обработки, но я хотел знать, есть ли эффективный способ сделать это с помощью async Task.

Сначала я попытался создать асинхронную задачу, но понял, что без await код не будет параллельным. Проблема, с которой я столкнулся, заключается в том, что я не хочу, чтобы основной поток блокировался и не требовал каких-либо результатов от задачи для продолжения.

Это окончательный код, который я использую:

private static async Task sendSceenshot(PushSocket socket, byte[] frame)
{
  await Task.Run(() => socket.TrySendFrame(frame));
}

private static void Screenshot()
{
  while (isRunning)
    {
      yield return new WaitForSeconds(1f);
      
      // Take the screenshot...
      // [...]
 
      // Send the frame in the background without blocking the main thread
      sendSceenshot(screenSocketWide, currentFrame);

      // Reset and prepare for next frame
      // [...]
}

Вы это делаете "по запросу" или в каждом кадре (обновлении)? Существуют асинхронные операции с изображениями, но преимущества зависят от контекста; например ленивая загрузка. Возможно, вам придется стоять в очереди при других обстоятельствах.

Gerry Schmitz 10.07.2024 03:38

@GerrySchmitz Мне нужно отправлять скриншот каждые полсекунды. Я делаю это с помощью корутины в Unity. Я пробовал использовать AsyncGPURead, но это не сработало должным образом :( Есть ли у вас какие-либо другие предложения?

dennisklad 10.07.2024 17:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для этого вы можете просто использовать метод Task.Run(). Он использует пул потоков за вас, поэтому вам не придется иметь дело с потоками вручную.

private static void Screenshot()
    {
        
        //set up socket and frame
        
        //the key part
        await Task.Run(() => socket.TrySendFrame(frame));
    }

См. это, чтобы более глубоко понять различия между Thread и Task.

Я не уверен, что вы имели в виду под «это не завершает работу программы», не могли бы вы уточнить?

Хорошо, но действительно ли это асинхронно или основной поток должен ждать, пока задача будет выполнена, чтобы перейти к следующему кадру?

dennisklad 09.07.2024 13:09

И функция должна быть определена как aync, верно? Ошибка: оператор await можно использовать только внутри асинхронного метода. Рассмотрите возможность пометки этого метода модификатором async и изменения типа возвращаемого значения на Task.

dennisklad 09.07.2024 13:12

он асинхронный, основной поток не должен ждать. Цитируя документы: «[Task.Run] ставит указанную работу в очередь для запуска в пуле потоков и возвращает прокси-сервер для задачи»

Olivér Raisz 09.07.2024 13:15

Да, так и должно быть async, ведь только этих методов можно ожидать.

Olivér Raisz 09.07.2024 13:15

поскольку вы все равно не ожидаете выполнения функции, вы также можете опустить await из Task.Run.

MakePeaceGreatAgain 09.07.2024 13:23

К сожалению, я не вижу от этого какого-либо существенного улучшения производительности. FPS в игре по-прежнему очень низкий, поскольку их отправляют из основного потока. В любом случае спасибо!

dennisklad 09.07.2024 14:14

Другие вопросы по теме