Я нашел этот подход полезным. Таким образом, вам не нужен класс и окончательный
btnInsert.addMouseListener(new MouseAdapter() {
private Statement _statement;
public MouseAdapter setStatement(Statement _stmnt)
{
_statement = _stmnt;
return this;
}
@Override
public void mouseDown(MouseEvent e) {
String name = text.getText();
String from = text_1.getText();
String to = text_2.getText();
String price = text_3.getText();
String query = "INSERT INTO booking (name, fromst, tost, price) VALUES ('"+name+"', '"+from+"', '"+to+"', '"+price+"')";
try {
_statement.executeUpdate(query);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}.setStatement(statement));
Правильный способ - использовать AfxBeginThread
или std::thread::detach
. Вы можете использовать диалог в основном потоке пользовательского интерфейса.
В качестве альтернативы вы можете сделать это в одном потоке, предполагая, что ваша функция может быть прервана и сломана в разные части. Например, предположим, что у вас есть функция, которая занимает 3 секунды:
Sleep(3000);
Она может быть разбита на 30 частей и смоделирована как
for (int i = 0; i < 30; i++)
Sleep(100);
Вы можете обновить краску после каждого хода. Обратите внимание, что другие диалоговые сообщения должны игнорироваться, потому что это один поток, и вы можете делать только одно за раз. Вы должны отключить элементы управления, чтобы пользователь знал, что диалог занят. Пример:
void update_paint()
{
MSG msg;
while(PeekMessage(&msg, m_hWnd, 0, 0, PM_REMOVE))
{
if(msg.message == WM_COMMAND && msg.wParam == IDCANCEL) { }//cancel reuested
if(msg.message == WM_PAINT ||
(msg.message >= WM_NCCALCSIZE && msg.message <= WM_NCACTIVATE) ||
(msg.message >= WM_NCMOUSEMOVE && msg.message <= WM_NCMBUTTONDBLCLK))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
void CMyDialog::single_thread()
{
MessageBox(L"start");
//disable child controls to let user know the dialog is busy
for(CWnd *p = GetWindow(GW_CHILD); p; p = p->GetWindow(GW_HWNDNEXT))
p->EnableWindow(FALSE);
for(int i = 0; i < 30; i++)
{
Sleep(100);
update_paint();
}
//enable child controls
for(CWnd *p = GetWindow(GW_CHILD); p; p = p->GetWindow(GW_HWNDNEXT))
p->EnableWindow(TRUE);
MessageBox(L"done");
}
Если функция не может быть прервана, необходимо запустить второй поток.
Проблема частично исправлена: кажется, что использование потоков предотвращает регулярное потребление сообщений, даже если это неблокирующий вызов.
Мое обходное решение состояло в том, чтобы вернуть управление в окно, чтобы оно могло потреблять сообщений:
// … thread stuff
for (auto nI = 0; nI < nCount; nI++)
{
// Heavy computing
nSleepStep = 5;
nSleepTime = 200;
while (nSleepTime > nSleepStep)
{
while(PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE))
{
switch( msg.message )
{
case WM_TIMER :
case WM_PAINT :
TranslateMessage( &msg );
DispatchMessage( &msg );
break;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(nSleepStep));
nSleepTime -= nSleepStep;
}
}