|
To be able to send a message to a thread using PostThreadMessage , you must have a message loop in the thread using either a GetMessage or a PeekMessage .
The message queue for the thread will be created when the first message is sent to the thread.
Both UI threads and worker threads can have message queues.
|
|
|
|
|
Just to amplify Superman's answer - as soon as the worker thread makes a USER call it changes from being a worker thread to a UI thread. And it's probably better to create an invisible window in what was your worker thread to act as a target for your inter-thread messages as otherwise you'll have to add special purpose code to handle messages with NULL window handles.
|
|
|
|
|
|
See, for instance, here[^].
Veni, vidi, vici.
|
|
|
|
|
|
Thanks
Here is now my code works I have created
a CDialog * in a CDialog
<pre lange='cs'>
void Cprogdialog::Process() // <== Modal Dialog
{
class CMainFrame;
UpdateData(TRUE); // read infoe
CFileDialog dlg(TRUE, _T("asm"), _T("*.asm"), OFN_ALLOWMULTISELECT);
dlg.m_ofn.lStructSize = sizeof(OPENFILENAME);
dlg.m_ofn.lpstrFilter = "*.asm,*.cbl,*.c";
dlg.m_ofn.lpstrInitialDir = "F:\\";
dlg.m_ofn.lpstrTitle = "Program Source Code";
if (dlg.DoModal() == IDOK)
AfxMessageBox("Waiting for program " +progname + "
InJobName " jobname,MB_OK);
CprogDebug *myprog; // instantiate a Debug Class <=== Modless Diloaf
</pre>
I then Create a thread in Which I have a Derived CAsynsocket Class
<b> Creating the Thread </b>
<pre lang='cs'>
myprog->progsocket = (SockCLeintThread *) AfxBeginThread
(RUNTIME_CLASSSockCLeintThread),
THREAD_PRIORITY_NORMAL,
0,CREATE_SUSPENDED);
</pre>
<b> The CWinThread Class itself </b>
<pre lang='cs'>
class SockCLeintThread : public CWinThread
{
public:
DECLARE_DYNCREATE(SockCLeintThread)
// DECLARE_DYNAMIC(SockCLeintThread)
// IMPLEMENT_DYNAMIC(SockCLientThread)
public:
CWnd *sendwindow;
CWnd *call_wnd;
CString buffer;
char thread_id[15];;
SockClient *thisocket; // <=== derived CAsynsocket
virtual BOOL InitInstance(); // Just for starters
// virtual int Run(); // keep on moving
// virtual int ExitInstance();
void receive_work(WPARAM , LPARAM);
void Sendit(WPARAM, LPARAM);
void Receiveit(WPARAM, LPARAM);
void sockoper(WPARAM, LPARAM);
LPCTSTR ipaddr;
UINT port;
BOOL idle; // looking for work
SockCLeintThread();
~SockCLeintThread();
struct {
unsigned int is_connected : 1;
} flags;
protected:
DECLARE_MESSAGE_MAP()
}
</pre>
<b> The CDialog myprog Class </b>
<pre lang='cs'>
class CprogDebug : public CDialog
{
DECLARE_DYNAMIC(CprogDebug)
public:
CString progname;
CString jobname;
CString start_addr;
CString end_addr;
CString as_id;
CString proglisting;
debugevent *debug_event_ptr;
HANDLE filemap;
HANDLE dbgmutex;
HANDLE dbgevent;
HANDLE hercprocess;
struct
{
unsigned int wait_for_prog : 1;
unsigned int prog_in_lpa : 1;
unsigned int prog_nucleus : 1;
unsigned int cics_prog : 1;
unsigned int mvs_exit : 1;
unsigned int trace_mode : 1; /* in trace mode */
unsigned int breakpt_set : 1;
unsigned int cpu_set :1;
} status;
UINT asid;
// void DoDataExchange(CDataExchange* pDX);
CProgedit *myedit;
BOOL OnInitDialog();
SockCLeintThread *progsocket; // <== CWinThread tcpip thread
DWORD Tcpipthread; // SockClientthread
CprogDebug(CWnd* pParent = NULL); // standard constructor
void receive_break_point(); // receive break point
SIZE get_line_number(char *); // get location of current break t
LRESULT break_set(WPARAM mywparam, LPARAM mylparam);
LRESULT break_point(WPARAM mywparam, LPARAM mylparam);
LRESULT receive_tcpip(WPARAM,LPARAM );
void OnRequestResize(NMHDR *,LRESULT *);
virtual ~CprogDebug();
void Build_data(char *);
// Dialog Data
enum { IDD = IDD_PROGDEBUG };
private:
char cpu[2]; // current cpu
struct {
BYTE sysmask; /* System mask (0 - 7) */
BYTE pkey; /* PSW Key (8 - 11) */
BYTE states; /* EC,M,W,P bits (12 - 15) */
BYTE asc; /* Address space control */
/* (16 - 17) */
BYTE cc; /* Condition code (18 - 19) */
BYTE progmask; /* Program mask (20 - 23) */
BYTE zerobyte; /* Zeroes (24 - 31) */
/* or (esame) (24 - 30) */
u_int /* Addressing mode (31 - 32) */
amode64:1, /* 64-bit addressing (31) */
amode:1, /* 31-bit addressing (32) */
zeroilc:1; /* 1=Zero ILC */
char zeroword[4]; /* esame only (33 - 63) */
char ia[8]; /* Instruction addrress */
/* (33 - 63) */
/* or (esame) (64 -127) */
char amask[4]; /* Address wraparound mask */
char intcode[2]; /* Interruption code */
BYTE ilc; /* Instruction length count */
BYTE unused;
} PSW;
char inst[6]; // machine code
char assem_inst[35]; // assembler mnumonic
char regs[16][16];
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual BOOL PreTranslateMessage(MSG* pMsg);
DECLARE_MESSAGE_MAP()
};
#define BUF_SIZE 300
class debugevent : public CEvent
{
private:
public:
LPVOID fileptr;
CMutex* mylock;
HANDLE filemap;
debugevent(BOOL Own, BOOL bManualReset,LPCTSTR lpszName,LPSECURITY_ATTRIBUTES lpsaAttribute);
};
</pre>
<b> I create the derived CASynSocket in the constrocter of the CWinthread Class on the heap </b>
<pre lang='cs'> SockCLeintThread::SockCLeintThread()
{
thisocket = new SockClient;
m_bAutoDelete = FALSE;
}
</pre>
accessing the the Derived CAsynsocket class in the CWinThread class I get exceptions
<pre lang='cs'>
void SockCLeintThread::Sendit(WPARAM count, LPARAM command)
{
thisocket->num_buff = count;
thisocket->AsyncSelect(FD_WRITE);
return;
}
</pre>
I set m_pMainWnd and m_pActiveWnd to (Cwnd *) myprog
<pre lang='cs'>
myprog->progsocket->m_pActiveWnd = (CWnd *) myprog;
myprog->progsocket->m_pMainWnd = (CWnd *) myprog;
</pre>
does that make it a UI interface able to get messages via PosThreadMessage
I am sure I doing something wrong as I keep on getting exceptions
Thanks
|
|
|
|
|
ForNow wrote: I am sure I doing something wrong
Well if you actually look at what you've posted you can see that none of your <pre> tags have taken, and also you have selected 'cs' as the language type instead of 'C++'.
|
|
|
|
|
Is it really that simple to change from Worker to UI
I thought you have to make the discision at design time
e.g. UI uses ::INITINSTANCE and uses the runtime class in the AFXBegeingThread
isn't a different design ??
|
|
|
|
|
Nope, as soon as you call a USER function the thread gets a message queue and woo hoo it's a UI thread. This includes things like RegisterWindow, CreateWindow...
What you're getting confused with is that MFC "worker" threads don't implement a message pump so if they call a USER function they'll get a message queue but there'll be no code (AFAIK, it's been 10 years since I did any serious MFC programming) to handle any messages that arrive.
|
|
|
|
|
|
Anything in USER.DLL, USER32.DLL - I have no idea if there's a USER64.DLL as I'm using my FreeBSD computer at the mo
|
|
|
|
|
A lot of people let the naming convention of the threads mislead them. The difference in the two threading schemes is really more of a description of how they'll be used (although the "UI" name is not a great description since it doesn't necessarily involve dealing with a user interface).
|
|
|
|
|
No, but you can implement your own messaging system if you like.
To do this you need a message queue and a worker thread that empties it and acts on the message. Any other part of your code can lob messages onto the queue, at the head or tail depending on priority. (Message addition needs synching).
I have used this kind of design a lot in all sorts of code and it can simplify complex things massively.
==============================
Nothing to say.
|
|
|
|
|
I would only do this if the queues provided by the framework isn't sufficient, otherwise UI threads are just easy to make anyways (might as well use them as is).
|
|
|
|
|
how to right vector of pointers to binary file ?
every pointer have diffrent size ,and i need to save to file and restore from file
|
|
|
|
|
it makes no sense to write a pointer to a file.
Asaf Shay wrote: every pointer have diffrent size
pointers are always the same size (4 bytes in Win32, 8 bytes in Win64)
are you trying to write the structures that the pointers point to to a file?
|
|
|
|
|
There are several things wrong here.
First of, all pointers will be of the same size.
On a 32-bit OS, all pointers are 4 bytes or 32-bits and on a 64-bit OS, all pointers are 8 bytes or 64-bits.
Secondly, you do not want to persist pointers to a file, because they will not be valid when you read it back into the program as the address is not guaranteed to be the same every time the program is run.
So what you need is to have a vector of objects/data type instead of a vector of pointers. This is the recommended method.
Have a method of the object to return the data to be persisted.
Typically this must be a structure.
In the main program iterate through the elements of the vector, call the method that returns the data to be persisted and write it to a file.
You can use any of the file operation routines like CreateFile /WriteFile or fopen /fwrite to do this.
You would also need a method of the object to put back the data when you read it from the file.
|
|
|
|
|
hi,tanks for the comments,my problem is i can write to file and read from it only if my program is running,if i close the program and open again and try to read from the file i get run time error
"vector iterator not dereferencable"
case 'd':{
file = fopen("final_proj.bin","w+b");
t = arr.begin();
fwrite( (*t), sizeof(figure3d), 1, file);
system("cls");
cout << "saved to file successfully\n"<<endl ;
fclose(file);
flushall();
}
case 'e'://restore from file
{
file = fopen("final_proj.bin" , "r+b" );
t = arr.begin();
fread ((*t), sizeof(figure3d) , 1 , file);
temp.push_back(*t);
temp[0]->print();
/*arr.push_back(*t);*/
fclose(file);
}
|
|
|
|
|
It could be because you're having a vector of pointers.
Change that to vector of copyable objects.
|
|
|
|
|
After frustrating experiments with CTabCtrl based classes I am using simple property sheets to have a tabbed pane in static splitter. Does the job for me, with one exception.
The standard property frame is a pop-up of default dimensions ( taken from the max page ) and when changed to child I can move it to the correct position in the splitter.
And here is the "but" - the right and bottom dimension are not correct( but usable) and the only way I figured it out to adjust it is to get the parent (splitter) frame dimensions.
Works, and here comes another but - these are the whole splitter frame dimensions.
I would like to know if there is a easy way to get just the right pane dimensions.
BTW - the panes are created with constant sizes.
I could just hack it and make the sizes global variables.
Here is my very basic code:
void C_RightPane_Form::OnProperties()
{
CRect rect;
GetClientRect(rect);
C_Splitter_Static *pCFrameWnd = (C_Splitter_Static*) GetParentFrame( );
ASSERT_VALID(pCFrameWnd);
pCFrameWnd->GetClientRect(rect); // whole frame
// TODO need only right pane
if (m_pPropFrame == NULL)
{
m_pPropFrame = new CPropertyFrame1;
//CRect rect(0, 0, 0, 0);
CString strTitle;
VERIFY(strTitle.LoadString(IDS_PROPSHT_CAPTION1));
if (!m_pPropFrame->Create(NULL, strTitle,
WS_CHILD |
!WS_POPUP | WS_CAPTION | WS_SYSMENU, rect, this))
{
delete m_pPropFrame;
m_pPropFrame = NULL;
return;
}
//m_pPropFrame->CenterWindow();
m_pPropFrame->MoveWindow(0,0,rect.right, rect.bottom);
}
Thanks for your time.
Vaclav
|
|
|
|
|
|
first - sorry about my english
i have two vector of pointers: arr - contain info and i want to copy from him for example the second element to new vector of pointers that call temp and delete the element from arr .how it can be done ?
i write somting and it's not good but i only attach the that you see what i mean
int choose;
cout<<"choose index number of the object you want to delete:";
cin >> choose;
temp.push_back(arr[choose]);
delete arr[choose];
arr.erase(arr.begin()+ choose);
|
|
|
|
|
a1_shay wrote: delete arr[choose];
Why are you deleting this object?
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> If it doesn't matter, it's antimatter.<
|
|
|
|
|
because this my exercise
the main idea is that i need to delete object.and later if the user choose case undo I WILL return from temp the object that i put out before
someone told me that i need to delete the object with delete and that only delete the object,from what i am traing i see that delete free the address of that pointer and that's why i can print the temp after that
void deleteobject(vector < figure3d *> &arr,int index,vector < figure3d *> &temp)
{
vector < figure3d * > :: iterator i=arr.begin();
temp.insert(temp.begin(),*i);
delete *i;
arr.erase(i);
temp[0]->print();
}
modified 1-Jun-12 18:14pm.
|
|
|
|
|
Well that will be difficult, considering you deleted the object you're pointing to.
delete arr[choose];
Doesn't remove the pointer from the array, it deletes the object pointed to by that pointer, and since you added the pointer to that object to the other vector, the pointer in the other vector now points to junk data.
Think of a pointer like an address, you gave your second vector an address to a house, then demolished the house. If it tries to go there, it won't find the house it expects to find.
|
|
|
|