На данный вопрос уже ответили:
Есть DataGridView
, он присоединен к SQLite
. При изменении БД вручную через запросы, пытаюсь изменить в режиме реального времени таблицу и отобразить на ней новые значения строк. И в месте, где я присоединяю DataSet
к своей DataGridView
, возникает данное исключение. Причем, исключение возникает не всегда, а после какого-то уже изменения или еще чего, сам точно это не поняд. Можете пожалуйста подсказать, как можно решить данную проблему?
con.Open();
sql = "select rowid, * from OpenPos";
adapOpenPos = new SQLiteDataAdapter(sql, con);
dsOpenPos = new DataSet();
adapOpenPos.Fill(dsOpenPos);
dataGridView1.DataSource = dsOpenPos.Tables[0];
dataGridView1.Columns[0].Visible = false;
dataGridView1.Columns[15].Visible = false;
con.Close();
Ошибка:
Недопустимая операция в нескольких потоках: попытка доступа к элементу управления, не из того потока, в котором он был создан.
Уберите явную выборку поля rowid
:
sql = "select * from OpenPos";
Звёздочка и так извлекает все поля, так что дополнительные указания мало того, что ничего не дают, так ещё и заставляют драйвер SQLite отказывать в выполнении подобного запроса.
Указание дополнительных полей имеет смысл только при использовании подхапросов и объединений. Тогда звёздочка относится к FROM
-выражению из основного запроса, а явно именованные поля ищутся в подзапросах:
sql = "SELECT bar.a, * FROM foo LEFT JOIN bar ON foo.key = bar.parent";
Данная проблема решается несколькими способами :
.NET не позволяет обращаться к контролам напрямую из других потоков.
Простой и неправильный способ : Отменяем проверку, из какого потока используется контрол
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
Для одного раза может и сработать, но делать так крайне не рекомендуется.
Использование методов Invoke/BeginInvoke
Эти методы выполняют указанные делегаты в том потоке, в котором контрол был создан. Invoke вызывает делегат синхронно, BeginInvoke - асинхронно. Чтобы определить, требуется ли Invoke используйте свойство InvokeRequired. Например, объявляем делегат
delegate void Del(string text);
и вызываем Invoke
textBox1.Invoke(new Del((s) => textBox1.Text = s), "newText");
Вместо объявления новых делегатов можно использовать готовые, Action или Func Пример готового, потоко-безопасного метода
void SetTextSafe(string newText)
{
if (textBox1.InvokeRequired)
textBox1.Invoke(new Action<string>((s) => textBox1.Text = s), newText);
else
textBox1.Text = newText;
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Доброго времени суток! Хочу создать игру викторинуНа подобие игры Борьба Умов
Подскажите, что не так с моим кодом для дешифровки текстаДетерминант и матрицу алгебраических дополнений находит правильно, проверял
На форме есть 2 гридаDataContext для формы - отдельный класс(ViewModel)