Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > UpdateData и поток


Автор: BIV 21.6.2012, 11:43
Всем доброе время суток!
Возникла такая сложность: Есть диалоговое окно и в ней текстовое поле IDC_EDIT1, которое названа переменной edit типом int. Есть поток, который пытается занести данные в edit и команды UpdateData

Код

UINT ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    int a=0;
    CpotokiDlg *qwe;
    for(;;)
    qwe->UpdateData(TRUE);
    a++;
    qwe->edit=a;
    qwe->UpdateData(FALSE);
    return 0;
}

BOOL CpotokiDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    
    ...

    edit=0;
    AfxBeginThread(ThreadProc, this); //Создание потока

    return TRUE;  // return TRUE  unless you set the focus to a control
}


Компиляция прошла успешно, но появляется окно с ошибкой
Run-Time Check Failure #3 - The variable 'qwe' is being used without being initialized.

Что я тут сделал не так?
Как мне обновить данные?

Автор: xTr1m 21.6.2012, 12:39
Тут, ты просто объявляешь указатель (он указывает "вникуда")
Код

CpotokiDlg *qwe;


а тут ты сразу его используешь
Код

qwe->UpdateData(TRUE);


как я понимаю между этими строками забыл
Код

qwe = reinterpret_cast<CpotokiDlg*>(param);


p.s. кстати, цикл 
Код

for(;;)
    qwe->UpdateData(TRUE);

бесконечный, поэтому код ниже этих строк никогда не выполнится. По-моему, задумывалось как-то так:

Код

UINT ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    int a=0;
    CpotokiDlg *qwe = reinterpret_cast<CpotokiDlg*>(param);

    for(;;)
   {
        qwe->UpdateData(TRUE);
        a++;
        qwe->edit=a;
        qwe->UpdateData(FALSE);
   }

    return 0;
}
BOOL CpotokiDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    
    ...
    edit=0;
    AfxBeginThread(ThreadProc, this); //Создание потока
    return TRUE;  // return TRUE  unless you set the focus to a control
}


Автор: BIV 21.6.2012, 12:46
Поправил
Код

UINT ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    CpotokiDlg *qwe = reinterpret_cast<CpotokiDlg*>(param);
    int a=5;
    for(;;){
    qwe->UpdateData(TRUE);
    a++;
    qwe->edit=a;
    qwe->UpdateData(FALSE);}
    return 0;
}


Но при компиляции Debug, то по прежнему ошибка, если компилить через Release, то нормально, прога запускается и выполняется цикл, но при выходе окно с надписей:
Unhandled exception at 0x7863e574 in potoki.exe: 0xC0000005: Access violation reading location 0x0000c266.

И после него второе:
No symbols are loaded for any call stack frame. The source code cannot be displayed.

Если запустить скомпилированную программу в папке, то вроде работает и ничего не вылетает.
Это нормально?

Добавлено через 8 минут и 40 секунд
Вот так при компиляции Release, при завершении ничего не выскакивает, а при Debug по прежнему не доволен

Код

UINT ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    CpotokiDlg *qwe = reinterpret_cast<CpotokiDlg*>(param);
    int a=5;
    for(;;)
    {
        a++;
        qwe->out(a);
    }
    return 0;
}

void CpotokiDlg::out(int a)
{
    UpdateData(TRUE);
    edit=a;
    UpdateData(FALSE);
}

Автор: xTr1m 21.6.2012, 13:03
Вообще проблема в том, что окна между потоками должны передаваться по HWND (ну так во всяком случае рекомендуется). Но вот такой код почему-то не работает. Может кто из более опытных знает. Мне тоже стало интересно, поэтому покопаюсь. 

Код

...
edit=0;
AfxBeginThread(ThreadProc, GetSafeHwnd()); //Создание потока
...

UINT ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    int a=0;
    HWND hWnd = reinterpret_cast<HWND>(param);
    CWnd *pWnd = CWnd::FromHandle(hWnd);
    CBug1Dlg *qwe = reinterpret_cast<CBug1Dlg*>(pWnd);
    
    for(;;)
    {
        qwe->UpdateData(TRUE);
        a++;
        qwe->edit=a;
        qwe->UpdateData(FALSE);
    }
    return 0;
}


Добавлено @ 13:07
Можно вот так

Код

UINT ThreadProc(LPVOID param)  //Создание потоковой функции 
{
    int a=0;
    HWND hWnd = reinterpret_cast<HWND>(param);
    CWnd *pWnd = CWnd::FromHandle(hWnd);
    CBug1Dlg *qwe = reinterpret_cast<CBug1Dlg*>(pWnd);
    
    CString str;
    for(;;)
    {
        str.Format(L"%d", ++a);
        qwe->GetDlgItem(IDC_EDIT1)->SetWindowText(str);
    }
    return 0;
}


но это без механизма UpdateData

Автор: BIV 21.6.2012, 13:27
qwe->GetDlgItem(IDC_EDIT1)->SetWindowText(str);
Работает, но у меня при завершении появляется окошко с ошибкой.

В моем случае не появлялась.
Говорят что в Release лучше не компилить, якобы это не безопасно. Хотелось бы знать почему. В Debug по прежнему не могу

Автор: xTr1m 21.6.2012, 13:31
странно. у меня такой пример завершается нормально. что пишет про ошибку? (хотя по-хорошему, нужно завершить поток)
а нельзя оставлять такой релиз, так как потом может всплыть что угодно и когда угодно, этакая мина, которая рано или поздно взорвется. Так как в дебаге просто предупреждают, что мол, нехорошо так делать.

ну вот так вот можно еще
Код

UINT ThreadProc(LPVOID param)  //Создание потоковой функции
{
    int a=0;
    HWND hWnd = reinterpret_cast<HWND>(param);
    CWnd *pWnd = CWnd::FromHandle(hWnd);
    CBug1Dlg *qwe = reinterpret_cast<CBug1Dlg*>(pWnd);
    
    CString str;
    for(;;)
    {
        CWnd *pEdit = qwe->GetDlgItem(IDC_EDIT1);
        if(NULL == pEdit || FALSE == ::IsWindow(hWnd))
            break;

        str.Format(L"%d", ++a);
        pEdit->SetWindowText(str);
    }
    return 0;
}

Автор: BIV 21.6.2012, 14:34
Все, ошибки возникали из-за моей глупости, как раз забыл поток завершить.
Думаю, проблема решена. Главное что работает)) xTr1m, спасибо!)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)