#c# #forms #winforms #window
Вопрос:
У меня проблема в том, что мое окно программы больше нельзя перемещать или реагировать, пока оно находится в наборе данных.функция заполнения.
У кого-нибудь есть идеи, почему это может быть?
using (OracleCommand cmd = new OracleCommand(sqlQuery)) { cmd.CommandType = CommandType.Text; cmd.Connection = oraCon; using (DataSet dSetHelper = new DataSet()) { using (OracleDataAdapter dataAdapter = new OracleDataAdapter()) { dataAdapter.SelectCommand = cmd; if (!File.Exists(projPath "/" tableNameFromRow "/" tableNameFromRow ".xml")) { currentTableName.Text = "Export: " tableNameFromRow; this.Refresh(); dataAdapter.Fill(dSetHelper); dSetHelper.WriteXml(projPath "/" tableNameFromRow "/" tableNameFromRow ".xml"); } } } }
Ответ №1:
если вы не используете какую-либо задачу или другой многопоточный метод, Windows form запускает один поток.
Вероятно, время ответа на ваш запрос слишком велико.
Таким образом, ваш основной поток не может реагировать на другой процесс, например, нажатие кнопки или другое событие.
Для решения вы можете перенести код в блок задач
var source = new CancellationTokenSource(); var token = source.Token; var task = Task.Run(() =gt; DoSomething(token), token);
и вы можете получить свои данные в этом блоке.
static void DoSomething(CancellationToken token) { ///oracle connection, get data, fill etc etc }
Ответ №2:
У кого-нибудь есть идеи, почему это может быть?
Да, проще говоря, ваша программа-это поток, единственной задачей которого является рисование пользовательского интерфейса. Это поток, который запускает любой код обработчика нажатия кнопки и т. Д., И он не должен быть занят в течение длительного времени. Когда вы выполняете 30-секундный запрос к базе данных, поток буквально перестанет рисовать пользовательский интерфейс, ожидая завершения запроса, и все ваши щелчки, перетаскивания и нажатия клавиш просто попадают в эту очередь сообщений, ожидающих, пока поток их обработает. Вероятно, через пару секунд Windows замечает, что поток пользовательского интерфейса перестал выполнять свою обычную работу по очистке очереди (очередь сообщений пользовательского интерфейса окна увеличивается и увеличивается, а не очищается), и он закрывает окно и помещает «не отвечает» в заголовок. Когда запрос к БД завершается, поток внезапно снова начинает обрабатывать сообщения пользовательского интерфейса, и приложение оживает
Вам не нужно, чтобы ваш поток пользовательского интерфейса был занят в течение длительного времени. Не заставляйте его выполнять работу ввода-вывода (диски, базы данных), которая занимает больше, чем, например, полсекунды. Для более длительной работы вы можете включить свой метод async
(опубликовать подпись метода, если вам нужна дополнительная помощь в этом) и сделать:
await Task.Run(_ =gt; { dataAdapter.Fill(dSetHelper); });
Если вы заполняете огромное количество данных, подумайте о других возможных последствиях; возможно, потоковая передача данных из базы данных с помощью считывателя, а не загрузка всего этого в набор данных. Если запрос выполняется медленно, возможно, посмотрите на способы его оптимизации; прикрепление пользовательского интерфейса к медленно выполняемому запросу обычно отдает его в руки пользователя, что может означать, что они делают такие вещи, как нажимают кнопку Выполнить запрос, когда они расстраиваются из-за того, что это занимает много времени, усугубляя проблему.. (подумайте об отключении кнопки во время выполнения запроса)
Если вы хотите упростить свой код, вам не нужен using
набор данных, и вам не нужно предоставлять команду/подключение к адаптеру данных; У DAs есть конструктор, который принимает sql и строку подключения, и они создают команду/подключение для вас, открывают его и удаляют. Это означает, что вы можете свести запрос DA к чему-то вроде:
using var da = new...(sql,con str); var dt = new DataTable(); da.Fill(dt);