Multithreading
От: Евгений Чечковский  
Дата: 13.06.01 14:40
Оценка:
Нужно создать новый поток, который отслеживал
бы изменения в файловой системе и обновлял
содержимое TreeView. Изменения ослеживаются
с помощью FindFirstChangeNotification и WaitForSingleObject.

Новый поток создаю с помощью AfxBeginThread().

Первый параметр — указатель на функцию, реализующую
поток. Вопрос в том, что если описать эту функцию как
член класса, из которого создаётся новый поток, то компилятор
выдаёт странную ошибку:

void CNewThrDlg::OnOK()
{
UINT (CNewThrDlg::*pFunction)(LPVOID pParam) = CNewThrDlg::MyNewThread;
AfxBeginThread(pFunction, &m_MyStruct);
}

...

UINT CNewThrDlg::MyNewThread(LPVOID pParam)
{
AfxMessageBox("New thread started");
return 0;
}

При компиляции выдаётся сообщение:

D:\Projects\WORK\NewThr\NewThrDlg.cpp(185) : error C2665: 'AfxBeginThread' :
none of the 2 overloads can convert parameter 1 from type 'unsigned int
(__thiscall CNewThrDlg::*)(void *)'

Но если описать эту функцию во внешнем h — файле, затем подключить его к
классу, создающему поток,
то поток создаётся нормально, но из этой функции невозможно вызвать метод
класса,
который обновляет содержимое TreeView:


AfxBeginThread(MyNewThread, &m_MyStruct);

...

UINT MyNewThread(LPVOID pParam)
{
....
Если здесь попытаться вызвать метод класса, создающего поток, то
получу ошибку типа:
D:\PROJECTS\WORK\Simpexp\FoldersView.cpp(518) : error C2352:
'FoldersView::FillFoldersTree' : illegal call of non-static member function
}

Вот такие вот дела...
Может есть какие мысли по этому поводу?

Thanks...
Re: Multithreading
От: VVV Россия  
Дата: 13.06.01 17:47
Оценка:
Здравствуйте Евгений Чечковский,

Сообщение об ошибке совершенно правильное, функция для потока не может быть нестатическим методом класса. Решение проблемы может быть такое:

class CNewThrDlg : ..{

static UINT fnThread(LPVOID pParam);
static CNewThrDlg *pThis;

CNewThrDlg::CNewThrDlg(..)
{
pThis=this;
}
};

CNewThrDlg *CNewThrDlg::pThis=NULL;

и тогда указатель на объект класса CNewThrDlg будет доступен из функции fnThread.

----
или такое: в качестве параметра для поточной функции передать указатель на себя (т.е. this)

AfxBeginThread(fnThread, this);

UINT
CNewThrDlg::fnThread(LPVOID pParam)
{
CNewThrDlg *pDlg=(CNewThrDlg*)pParam;
...
}



ЕЧ>Нужно создать новый поток, который отслеживал

ЕЧ>бы изменения в файловой системе и обновлял
ЕЧ>содержимое TreeView. Изменения ослеживаются
ЕЧ>с помощью FindFirstChangeNotification и WaitForSingleObject.

ЕЧ>Новый поток создаю с помощью AfxBeginThread().


ЕЧ>Первый параметр — указатель на функцию, реализующую

ЕЧ>поток. Вопрос в том, что если описать эту функцию как
ЕЧ>член класса, из которого создаётся новый поток, то компилятор
ЕЧ>выдаёт странную ошибку:

ЕЧ>void CNewThrDlg::OnOK()

ЕЧ>{
ЕЧ>UINT (CNewThrDlg::*pFunction)(LPVOID pParam) = CNewThrDlg::MyNewThread;
ЕЧ>AfxBeginThread(pFunction, &m_MyStruct);
ЕЧ>}

ЕЧ>...


ЕЧ>UINT CNewThrDlg::MyNewThread(LPVOID pParam)

ЕЧ>{
ЕЧ>AfxMessageBox("New thread started");
ЕЧ>return 0;
ЕЧ>}

ЕЧ>При компиляции выдаётся сообщение:


ЕЧ>D:\Projects\WORK\NewThr\NewThrDlg.cpp(185) : error C2665: 'AfxBeginThread' :

ЕЧ>none of the 2 overloads can convert parameter 1 from type 'unsigned int
ЕЧ>(__thiscall CNewThrDlg::*)(void *)'

ЕЧ>Но если описать эту функцию во внешнем h — файле, затем подключить его к

ЕЧ>классу, создающему поток,
ЕЧ>то поток создаётся нормально, но из этой функции невозможно вызвать метод
ЕЧ>класса,
ЕЧ>который обновляет содержимое TreeView:


ЕЧ>AfxBeginThread(MyNewThread, &m_MyStruct);


ЕЧ>...


ЕЧ>UINT MyNewThread(LPVOID pParam)

ЕЧ>{
ЕЧ>....
ЕЧ>Если здесь попытаться вызвать метод класса, создающего поток, то
ЕЧ>получу ошибку типа:
ЕЧ>D:\PROJECTS\WORK\Simpexp\FoldersView.cpp(518) : error C2352:
ЕЧ>'FoldersView::FillFoldersTree' : illegal call of non-static member function
ЕЧ>}

ЕЧ>Вот такие вот дела...

ЕЧ>Может есть какие мысли по этому поводу?

ЕЧ>Thanks...
Re: Multithreading
От: Irokez  
Дата: 13.06.01 17:55
Оценка:
Здравствуйте Евгений Чечковский, вы писали:

Все вполне просто объясняется. В любой член-функции первым параметром идет неявный указатель this, поэтому функция потока для компилятора выгладит примерно так void CMyClass::MyThread(CMyClass* this, LPVOID pParam), что немного отличается от функции потока :). Решение два.
1) Либо объявить член функцию класс(которая является функцией потока) типа static. Тогда в нее не будет передаваться неявный казатель this. Но обращять можно будет из нее, только к static член-функциям или член-данным.
2) Зделать функцию потока глобальной(Не член функцией класса).

Вот и все...
Re: Multithreading
От: offsider Украина  
Дата: 15.06.01 07:31
Оценка:
В документации на MFC есть ограничение на использование в потоках классов производных от CObject
(в том числе и CWnd).
Чтобы использовать в разных потока одно окно диалога, нужно передать дочернему потоку Хэндл окна.
А в потоке вызвать CWnd::FromHandle(m_hWnd).
В твоём случае нужно сделать так:

//Объявляем глобальную ф-ию потока

UINT MyNewThread(LPVOID pParam)
{
HWND *hWnd=(HWND*) pParam;
CNewThrDlg* dlg=(CNewThrDlg*)CWnd::FromHandle(*hWnd);
//здесл используем dlg...
//dlg->m_tree ... и т.д.
}

//в классе диалога

void CNewThrDlg::OnOk()
{
AfxBeginThread(MyNewThread, &m_hWnd);
}

не уверен в работоспособности этого кода, но...



Удачи!
__________________________________________________________ :)
Compiling...
message.cpp(4):error C2059: Can't understand russian mat :'@#$^& '
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.