Вопрос ожидания пула потоков и графического интерфейса пользователя

StackOverflow https://stackoverflow.com/questions/375314

  •  22-08-2019
  •  | 
  •  

Вопрос

Я новичок в потоках и нуждаюсь в помощи.У меня есть приложение для ввода данных, которому требуется непомерное количество времени, чтобы вставить новую запись (т. е. 50-75 секунд).Итак, мое решение состояло в том, чтобы отправить инструкцию insert через ThreadPool и позволить пользователю начать вводить данные для записи во время этой вставки, которая возвращает новый идентификатор записи во время выполнения этой вставки.Моя проблема в том, что пользователь может нажать сохранить до того, как новый идентификатор будет возвращен из этой вставки.

Я попытался ввести логическую переменную, которой присваивается значение true через событие из этого потока, когда его безопасно сохранять.Затем я вставил в

while (safeToSave == false)  
{  
    Thread.Sleep(200)  
}  

Я думаю, что это плохая идея.Если я запущу метод save до того, как этот протектор вернется, он застрянет.

Итак, мои вопросы таковы:

  1. Есть ли лучший способ сделать это?
  2. Что я здесь делаю не так?

Спасибо за любую помощь.
Дуг

Отредактируйте для получения дополнительной информации:

Он выполняет вставку в очень большую (приближающуюся к максимальному размеру) базу данных FoxPro.Файл содержит около 200 полей и почти столько же индексов в нем.
И прежде чем вы спросите, нет, я не могу изменить его структуру, поскольку она была здесь до меня, и в нее попала тонна устаревшего кода.Первая проблема заключается в том, что для того, чтобы получить новый идентификатор, я должен сначала найти max (id) в таблице, затем увеличить его и увеличить контрольную сумму.Это занимает около 45 секунд.Затем первая вставка - это просто вставка этого нового идентификатора и поля enterdate.Эта таблица не является / не может быть помещена в DBC, так что исключает автоматическую генерацию идентификаторов и тому подобное.

@джошуа.кувшин
У вас правильный процесс, и я думаю, что на короткий срок я просто отключу кнопку сохранить, но я рассмотрю вашу идею о передаче ее в очередь.Есть ли у вас какие-либо ссылки на MSMQ, на которые мне следует взглянуть?

Это было полезно?

Решение

Все остальные, включая вас, рассмотрели основные проблемы (время вставки, почему вы делаете вставку, затем обновляете), поэтому я остановлюсь только на технических проблемах с вашим предлагаемым решением.Итак, если я правильно настрою поток:

  • Поток 1:Начните ввод данных для записи

  • Поток 2:Фоновые вызовы в базу данных для получения нового идентификатора

  • Кнопка сохранить всегда включена, если пользователь попытается сохранить до завершения потока 2, вы переводите # 1 в спящий режим на 200 мс?

Самый простой, но не лучший ответ - просто отключить кнопку и попросить этот поток создать обратный вызов делегату, который включает кнопку.Они не смогут запустить операцию обновления, пока вы не будете уверены, что все настроено надлежащим образом.

Хотя, я думаю, что гораздо лучшим решением (хотя оно может быть раздутым, если вы просто создаете интерфейс Q & D для FoxPro) было бы поместить эти операции сохранения в очередь.Пользователь может вводить ключ как можно быстрее, затем запросы помещаются во что-то вроде MSMQ, и они могут выполняться в свое время асинхронно.

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

1) Многие :), например, вы могли бы отключить кнопку "Сохранить", пока поток вставляет объект, или вы можете настроить Thread Worker, который обрабатывает очередь "запросов на сохранение" (но я думаю, проблема здесь в том, что пользователь хочет изменить вновь созданную запись, поэтому отключение кнопки, возможно, лучше)

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

кстати, я просто не понимаю, почему вставка должна занимать так много времени..Я думаю, что вы должны сначала проверить этот код!<- точно так же, как Чарльз заявлял ранее (извините, не читал пост) :)

Используйте будущее вместо необработанного действия ThreadPool.Выполните будущее, разрешите пользователю делать все, что он хочет, когда он нажмет Сохранить во 2-й записи, запросите значение из будущего.Если 1-я вставка уже завершена, вы сразу получите идентификатор, и 2-я вставка будет разрешена к запуску.Если вы все еще ожидаете выполнения 1-й операции, будущее будет заблокировано до тех пор, пока оно не станет доступным, и тогда можно будет выполнить 2-ю операцию.

Вы не экономите никакого времени, если только пользователь не работает медленнее, чем сама операция.

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

Во-вторых, почему вы вставляете запись до того, как у вас будут данные?Обычно приложения для ввода данных кодируются таким образом, что вставка не выполняется до тех пор, пока от пользователя не будут собраны все необходимые данные для вставки.Вы делаете это потому, что сначала пытаетесь вернуть новый идентификатор из базы данных, а затем "обновить" новую пустую запись введенными пользователем данными позже?Если это так, то почти у каждого поставщика баз данных есть механизм, с помощью которого вы можете выполнить вставку только один раз, не зная нового идентификатора, и заставить базу данных также вернуть новый идентификатор...Какую базу данных поставщиков вы используете?

Возможно ли подобное решение:

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

PS:Это трудно подтвердить, но имейте в виду следующую проблему параллелизма с тем, что вы предлагаете (с потоками или без них):Пользователь A, начинает добавлять, пользователь B начинает добавлять, пользователь A вычисляет ID 1234 как максимальный свободный идентификатор, пользователь B вычисляет ID 1234 как максимальный свободный идентификатор.Пользователь A вставляет идентификатор 1234, Пользователь B вставляет идентификатор 1234 = Бум!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top