Можно ли принудительно завершить работу std::sort?
У меня есть основной поток, который содержит в себе бесконечный цикл, который дожидается другой поток, занимающийся сортировкой.
// Инициализация потока для работы с сортировкой файла
const poco::Runnable::Ptr sortingRunnable(new SortingRunnable(this));
poco::Thread sortingThread;
// Флаг, отсортирован ли файл
_isSorted = false;
// Запуск сортировки
sortingThread.start(sortingRunnable);
// Выставление ProgressBar в бесконечное состояние
_processForm->showProgress();
_processForm->initProgress(0, 0);
// Скрываем поля, оставив только ProgressBar
_processForm->hideLabelsAndCounters();
// Перерисовываем ProgressBar для прокрутки "бесконечной" загрузки
for (;;)
{
_processForm->repaintProgress();
// Если файл будет отсортирован, но выходим из цикла
if (_isSorted)
break;
// Если во время сортировки файла, пользователь нажмёт ( Отмена ), то прозводим выход
checkApplicationMessage();
// Принудительно вызываю обработку накопившихся событий
QApplication::processEvents();
}
// Ждём поток, отвечающий за сортировку
sortingThread.join();
Как можете видеть я создаю Runnable библиотеки poco, и в нём вызываю асинхронную сортировку. Соотвественно я и дожидаюсь результата этой сортировки в бексонечном цикле цикле. Сама сортировка вот:
class SortingRunnable : public poco::Runnable {
public:
explicit SortingRunnable(ImportMaster* import) : _import(import) {}
~SortingRunnable() {}
void run() override
{
auto sorting = [&](const QStringList& str1, const QStringList& str2) -> bool
{
if (str1.empty() || str2.empty())
return false;
QChar char1;
QChar char2;
if (!str1[0].isEmpty() && !str2[0].isEmpty())
{
char1 = str1[0][0];
char2 = str2[0][0];
}
const poco::UInt8 SYMBOL = 0x0000007E;
if ((char1 == SYMBOL && char2 == SYMBOL) || (char1 != SYMBOL && char2 != SYMBOL))
return naturalSorting(str1.join(',').toStdString(), str2.join(',').toStdString());
if (char1 != SYMBOL && char2 == SYMBOL)
return false;
if (char1 == SYMBOL && char2 != SYMBOL)
return true;
return false;
};
std::sort(_import->_strings.begin(), _import->_strings.end(), sorting);
_import->_isSorted = true;
}
private:
ImportMaster* _import;
};
Теперь основной вопрос. Функция checkApplicationMessage(); вызывает обработку отмены процесса импорта, который в основной поток кидает исключение, которое я могу успешно отловить и обработать как мне нужно. Но как мне сказать потоку Runnable остановить процесс std::sort (сортировки)?
Ответы (1 шт):
Решением для данной задачи я нашёл один путь. На просторах интернета обнаружил, что можно кидать исключения в std::sort обработке. Что я и сделал, создал атомарный флаг, который выставляется во время выброса исключения.
void run() override
{
auto sorting = [&](const QStringList& str1, const QStringList& str2) -> bool
{
if (_import->_isSortedStoped)
throw poco::Exception("Stoped sorting");
if (str1.empty() || str2.empty())
return false;
QChar char1;
QChar char2;
if (!str1[0].isEmpty() && !str2[0].isEmpty())
{
char1 = str1[0][0];
char2 = str2[0][0];
}
const poco::UInt8 SYMBOL = 0x0000007E;
if ((char1 == SYMBOL && char2 == SYMBOL) || (char1 != SYMBOL && char2 != SYMBOL))
return naturalSorting(str1.join(',').toStdString(), str2.join(',').toStdString());
if (char1 != SYMBOL && char2 == SYMBOL)
return false;
if (char1 == SYMBOL && char2 != SYMBOL)
return true;
return false;
};
try
{
std::sort(_import->_strings.begin(), _import->_strings.end(), sorting);
}
catch (...)
{
_import->_isSorted = true;
return;
}
_import->_isSorted = true;
}
Для ловли исключения в основном потоке создал обёртку над функцией и разорвал поток обработки detach`ем.
// Инициализация потока для работы с сортировкой файла
const poco::Runnable::Ptr sortingRunnable(new SortingRunnable(this));
poco::Thread sortingThread;
// Флаг, отсортирован ли файл
_isSorted = false;
_isSortedStoped = false;
// Запуск сортировки
sortingThread.start(sortingRunnable);
sortingThread.detach();
// Выставление ProgressBar в бесконечное состояние
_processForm->showProgress();
_processForm->initProgress(0, 0);
// Скрываем поля, оставив только ProgressBar
_processForm->hideLabelsAndCounters();
// Перерисовываем ProgressBar для прокрутки "бесконечной" загрузки
for (;;)
{
_processForm->repaintProgress();
// Если файл будет отсортирован, но выходим из цикла
if (_isSorted)
break;
// Если во время сортировки файла, пользователь нажмёт ( Отмена ), то прозводим выход
try
{
checkApplicationMessage();
}
catch (poco::Exception& ex)
{
_isSortedStoped = true;
throw ex;
}
// Принудительно вызываю обработку накопившихся событий
QApplication::processEvents();
}
if (sortingThread.joinable())
// Ждём поток, отвечающий за сортировку
sortingThread.join();
Теперь всё стало работать как мне и нужно было.