Продолжение задачи с контекстом «use_current» не работает

Я пытался найти ответ на этот вопрос три дня назад. Либо я сделал что-то в корне неправильное (что является очевидной ошибкой), либо это слишком ново, чтобы иметь какие-либо ссылки, я не могу понять, почему простые случаи, подобные этому, потерпят неудачу.

В следующем коде используется библиотека задач PPL в C ++ в приложении Windows Store, имитирующая операцию загрузки файла, которая занимает 2 секунды до выхода из цикла (конечно, это для иллюстрации проблемы с минимальными кодами, реальный цикл выполняет другой рендеринг для показать прогресс тоже).

Часть кода продолжения (то есть «fileLoaded = true») никогда не вызывается, если я использую «use_current» в качестве контекста продолжения:

bool fileLoaded = false;
while (!fileLoaded)
{
concurrency::task<void>([this]()
{
// Simulate file load delay
concurrency::wait(2000);

}).then([this, &fileLoaded]()
{
fileLoaded = true; // This never gets executed!

// If the following is changed to "use_default" or
// "use_arbitrary", then this continuation gets called.
}, concurrency::task_continuation_context::use_current());

concurrency::wait(50);
}

Тот же код работает, если я использую «use_default» или «use_arbitrary» и правильно устанавливаю «fileLoad» в «true». Этот код может быть помещен в любое место приложения C ++ для Магазина Windows (например, приложения Direct2D), и он потерпит неудачу (я поместил его в тело конструктора «DirectXPage :: DirectXPage», которое, как я ожидаю, будет основным потоком пользовательского интерфейса). Я сделал что-то ужасно неправильно?

Заранее спасибо за помощь! 🙂

1

Решение

Так как ты звонишь .then() в потоке пользовательского интерфейса, use_current() приведет к тому, что продолжение будет запланировано для выполнения в потоке пользовательского интерфейса.

Однако это продолжение не может выполняться до тех пор, пока поток пользовательского интерфейса не освободится (то есть, когда он не выполняет никакой работы). Но в вашем примере поток пользовательского интерфейса никогда не бывает свободным: DirectXPage Конструктор работает в потоке пользовательского интерфейса. DirectXPage конструктор не вернется, пока не выполнится продолжение, а продолжение не может быть выполнено, пока DirectXPage конструктор возвращает.

Необходимо разрешить возврат конструктору, чтобы поток пользовательского интерфейса мог свободно выполнять другую работу (например, выполнить продолжение).


Также обратите внимание, что если вы используете fileLoaded для связи между потоками необходимо использовать std::atomic<bool> или какой-то другой правильный объект синхронизации. Просто bool недостаточно для синхронизации.

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]