I have been building a simple application which requires a separate thread to run some background code in a while
loop. I have a text box which I want to send messages to from the code running in the separate thread however I am unable to.
A non static member reference must be relative to a specific object. From my understanding to run an additional thread it seems that I have to make the function static
. However when I try and write a message to m_Console
I see the error:
A non static member reference must be relative to a specific object.
I tried initialising the object but it doesn't do anything.
CMFCApplication1Dlg obj;
obj.m_Console = "Test"
The code that uses a separate thread is:
static UINT checkSomething(LPVOID pParam);
The text box variable is:
CString m_Console;
void CMFCApplication1Dlg::OnBnClickedBtnAdd(){
m_Console = "Parser is now running..";
AfxBeginThread(checkSomething,"");
I have tried the suggestion:
UINT CMFCApplication1Dlg::checkSomething(LPVOID pParam){
CMFCApplication1Dlg* pObject = (CMFCApplication1Dlg*)pParam;
pObject->m_Console = "I am in thread";
But it throws an access violation error on: pObject->m_Console = "I am in thread";
Exception thrown at 0x0FE90DBD (mfc140ud.dll) in MFCApplication1.exe: 0xC0000005: Access violation reading location 0xFFFFFFFC.
Here is the code:
MFCApplication1Dlg.cpp
void CMFCApplication1Dlg::OnBnClickedBtnAdd(){
m_Console = "Something Parser is now running..";
AfxBeginThread(checkSomething,"");
CWnd* okbtn = GetDlgItem(IDC_BTN_ADD);
if (okbtn) {
okbtn->EnableWindow(FALSE);
}
// without UpdateData() status area will _NOT_ be updated.
UpdateData(FALSE);}
INT CMFCApplication1Dlg::checkSomething(LPVOID pParam){
CMFCApplication1Dlg* pObject = (CMFCApplication1Dlg*)pParam;
pObject->m_Console = "I am in thread";
MFCApplication1Dlg.h
public:
afx_msg void OnBnClickedBtnAdd();
static int messenger();
static UINT checkSomething(LPVOID pParam);
CString m_Console;
Textbox: IDC_Console
From reading everyone's comments, it seems as if this is something that I am not supposed to do in C++, question is then, what if I had a background task running a loop in in a separate thread which needed to update the status box on the UI? To me that seems a logical thing someone might wish to do but if I'm not supposed to do that then how would that be done? I am running the task in a separate thread because it uses a while loop and if I don't use a separate thread it just freezes the whole application.
You can deliver the object of CMFCApplication1Dlg as parameter for the Thread function.
e.g
UINT MyThreadProc( LPVOID pParam )
{
CMFCApplication1Dlg * pObject = (CMFCApplication1Dlg *)pParam;
pObject->m_Console = "I am in thread";
}
// .... .... ...
AfxBeginThread(MyThreadProc, this);
I hope this answer will work for you.
Changed
AfxBeginThread(checkSomething,""); to
AfxBeginThread(checkSomething,this);
as suggested by ysk silver, thanks!
I needed to add a Timer Function which I followed this article: https://www.tutorialspoint.com/mfc/mfc_multithreading.htm
Once I did this, the UI box updates.
int currValue;int maxValue;BOOL stopNow;string output;
BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_ERASEBKGND()
ON_WM_CTLCOLOR()
ON_WM_TIMER() //TIMER
ON_BN_CLICKED(IDC_BTN_ADD, &CMFCApplication1Dlg::OnBnClickedBtnAdd)
END_MESSAGE_MAP()
void CMFCApplication1Dlg::OnTimer(UINT_PTR nIDEvent) {
CDialogEx::OnTimer(nIDEvent);
UpdateData(FALSE);}
void CMFCApplication1Dlg::OnBnClickedBtnAdd(){
SetTimer(1234, 333, 0); // 3 times per second
m_Console = "Parser is now running..";
AfxBeginThread(checkSomething,this);
I then can change the text in the checkSomething method:
CMFCApplication1Dlg* pObject = (CMFCApplication1Dlg*)pParam;
output = "I am in thread";
pObject->messenger(output);
//OR
pObject->m_Console = "I am in thread";
And the textbox updates!
User contributions licensed under CC BY-SA 3.0