// ================================================ ========================================
// Title:
// Data exchange between events and processes
// Author:
// Norains
// Date:
// Monday 13-July-2009
// Environment:
// Wince5.0 + vs2005
// ================================================ ========================================
Multi-threaded data communication is not difficult. After all, it is the same process. More importantly, the Code may also belong to the same project, big deal I use a global variable for caching for data exchange.
But it is not that easy for multiple processes. From the code perspective, multi-process means different projects, meaning that data cannot be exchanged simply by using global variables. Imagine if IE has a global variable g_icurpage, how can you get the data? Therefore, in the case of multi-process, there is no such thing as multithreading.
However, if you only exchange data, the situation is not that bad. The general process is nothing more than: assume there are two, namely process a and process B. When thread a changes some values, it sends the corresponding event to process B; after receiving the notification event, process B reads the value changed by process a in a certain way.
Does it sound simple?
Before discussing this issue, let's assume that the two processes have the following Architecture code.
Process A: <br/> DWORD policyproc (lpvoid pparam) <br/>{< br/> while (true) <br/>{< br/> If (isdatachange ()! = False) <br/>{< br/> // todo: Prepare the transmitted data </P> <p> pulseevent (heventnotify ); <br/>}</P> <p> process B: <br/> DWORD waitpolicyproc (lpvoid pparam) <br/>{< br/> while (true) <br/>{< br/> DWORD dwreturn = waitforsingleobject (heventnotify); <br/> If (dwreturn! = Wait_timeout) <br/>{< br/> // todo: obtain the corresponding data <br/>}< br/>}
From this simple code, we can know that there are two difficulties: first, how process a prepares data, and second, how process B obtains data prepared by process.
The methods to be discussed are discussed based on the two difficulties of this framework.
Generally, there are only three methods.
1). Registry
The complete code after using this method is as follows:
Process A: <br/> DWORD policyproc (lpvoid pparam) <br/>{< br/> while (true) <br/>{< br/> If (isdatachange ()! = False) <br/>{< br/> // change the corresponding registry value <br/> CREG reg; <br/> Reg. create (HKEY_CURRENT_USER, device_info); <br/> Reg. setdw (main_volume, dwval); <br/> Reg. close (); </P> <p> // send a notification event <br/> pulseevent (heventnotify ); <br/>}</P> <p> process B: <br/> DWORD waitpolicyproc (lpvoid pparam) <br/>{< br/> while (true) <br/> {<br/> // wait for a notification event <br/> DWORD dwreturn = waitforsingleobject (heventnotify ); </P> <p> If (DW Return! = Wait_timeout) <br/>{< br/> // read the registry <br/> CREG reg; <br/> Reg. create (HKEY_CURRENT_USER, device_info); <br/> DWORD dwval = 0; <br/> dwval = reg. getdw (main_volume); <br/>}< br/>}
This method is highly flexible. If process a wants to add more notification data, it simply needs to set multiple registry entries. Process B does not need to worry about the number of registry entries set by process a. It only needs to obtain the project it needs.
Another obvious advantage is that, because this method saves data in the registry, process B can obtain data after process a exits. Even after the machine is restarted, process B can still obtain the relevant data, provided that the Registry of the system is hive registry.
If the defect is said to be accurate, it is speed compared to the other two methods. Because the registry will be read and written during this period, the speed will be slightly reduced. If you are very concerned about the speed, this method is not the best.
2). Memory Printing
In fact, this way in my blog another article "data sharing between processes" (http://blog.csdn.net/norains/archive/2008/07/16/2663390.aspx) has been mentioned, but for the integrity of this article, here we will discuss it again based on our discussion framework.
The principle is very simple. process a first calls createfilemapping to open up an inprint memory zone, then copies the data to it, and finally notifies process B to read the data. When process B receives the notification, you can directly call memcpy to retrieve data from the memory.
Process A: <br/> DWORD policyproc (lpvoid pparam) <br/>{< br/> // create a memory file print <br/> handle hfile = createfilemapping (handle)-1, null, page_readwrite, 0, mem_size, mem_1__name); </P> <p> void * pmem = NULL; <br/> If (hfile! = NULL) <br/>{< br/> pmem = mapviewoffile (hfile, file_map_all_access, 0, 0 ); <br/>}</P> <p> while (true) <br/> {<br/> If (isdatachange ()! = False) <br/>{< br/> // copy the transmitted data <br/> If (pmem! = NULL) <br/>{< br/> memcpy (pmem, & dwvalue, sizeof (dwvalue )); <br/>}</P> <p> pulseevent (heventnotify); <br/>}</P> <p> // if it is no longer used, close the handle <br/> closehandle (hfile); </P> <p >}</P> <p> process B: <br/> DWORD waitpolicyproc (lpvoid pparam) <br/>{< br/> // create a memory file print <br/> handle hfile = createfilemapping (handle)-1, null, page_readwrite, 0, mem_size, mem_1__name); </P> <p> void * pmem = NULL; <br/> If (hfile! = NULL) <br/>{< br/> pmem = mapviewoffile (hfile, file_map_all_access, 0, 0 ); <br/>}</P> <p> while (true) <br/>{< br/> DWORD dwreturn = waitforsingleobject (heventpolicy ); <br/> If (dwreturn! = Wait_timeout) <br/>{< br/> // copy the transmitted data <br/> If (pmem! = NULL) <br/>{< br/> memcpy (& dwvalue, pmem, sizeof (dwvalue )); <br/>}</P> <p> // close the handle if it is no longer in use <br/> closehandle (hfile ); <br/>}
This method is the most complex. The two processes not only collaboratively set the memory size (mem_size), but also set the same name (mem_memory _name), but also determine whether the memory can be allocated successfully. Relatively, the flexibility is also the highest. As long as the above problem is resolved through negotiation, any data type can be passed, whether it is DWORD or struct. Of course, we still cannot pass the object pointer, because simply passing the object pointer will basically cause a fatal error in memory access violation.
3). Set event data
Compared with the above two methods, this method can only be lightweight. Because it is the simplest method, it also delivers the least data.
The principle is very simple. process a sets the data associated with the event through seteventdata, and then sends the Event Notification to process B. After process B receives the event of process a, it obtains data through geteventdata. Based on this principle, the Code style can be as follows:
Process A: <br/> DWORD policyproc (lpvoid pparam) <br/>{< br/> while (true) <br/>{< br/> If (isdatachange ()! = False) <br/>{< br/> // sets the associated data <br/> seteventdata (heventnotify, dwdata); </P> <p> pulseevent (heventnotify ); <br/>}</P> <p> process B: <br/> DWORD waitpolicyproc (lpvoid pparam) <br/>{< br/> while (true) <br/>{< br/> DWORD dwreturn = waitforsingleobject (heventnotify); <br/> If (dwreturn! = Wait_timeout) <br/>{< br/> // obtain associated data <br/> dwdata = geteventdata (heventnotify ); <br/>}< br/>}
This method is the simplest, and has a unique advantage in transferring data of the DWORD length type, whether it is speed or simplicity. However, it is also limited to this. If you want to use this method to pass a value greater than DWORD, precision will basically be lost, not to mention struct values such as struct. However, these three methods are most closely related to events.