I am trying to create a new process from an existing process.
like that parentMain process creates childMain process.
my goal is:
1) Both process will continue running (means no one should wait for another to finish)
2) The creator - parentMain process, should send a message to the created process - childMain process.
I do not know when the new childMain process is actually ready. I can not use the wait function as I understood it waits until
the child process should end, but my aim is it will continue to run.
After little googling I am using the fork & exec family functions as follows:
void parentMain::CreateAndSend()
{
createNewProcess();
sendMessage();
}
void parentMain::createNewProcess()
{
char* param1[10] = "param1";
// Create new process.
cpid = fork();
if (cpid >= 0) // fork() succeeded.
{
if (cpid == 0) // 0 for child process.
{
execl("/home/kon/childMain", "/home/kon/childMain", param1, (char*)0);
}
else /* parent process */
{
printf("Parent process, parent PID=%d child PID=%d, getpid(), cpid);
}
}
else // fork() failed.
{
printf("Failure");
}
}
void parentMain::sendMessage()
{
Y = 50; // milliseconds.
nanosleep(Y);
?? isChildReady ??
sendChildMessage();
}
Now, sometimes sendMessage() fails!
if I am using a sleep(X) it succeeded. (in seconds)
but I want to reduce the time as much as I can.
How much time it takes to a process to be created?
is there any function that says "child is ready"?
How can I do it?
Thanks
Related
I am developing an application library using GTK and the functions for threads in GLib. I have a thread (from now on will be called thread A) that is created when I hit an "ok" button in a certain graphical window. Thread A starts doing some heavy tasks. Another button named "cancel" is available to stop and finish thread A at any moment.
My aim is to code a function for the thread created when I hit the "cancel" button (thread B) that has the ability to end the thread A.
I create thread A with the function g_thread_create. However I cannot find any function similar to g_thread_cancel to stop thread A using thread B. Is this possible or cannot be done?
Thank you so much for any kind of information provided.
You might want to consider using GTask to run your task in a thread, rather than using a manually-created thread. If you use g_task_run_in_thread(), the operation will run in a separate thread automatically.
GTask is integrated with GCancellable, so to cancel the operation you would call g_cancellable_cancel() in the callback from your ‘Cancel’ button.
As OznOg says, you should treat the GCancellable as a way of gently (and thread-safely) telling your task that it should cancel. Depending on how your long-running task is written, you could either check g_cancellable_is_cancelled() once per loop iteration, or you could add the GSource from g_cancellable_source_new() to a poll loop in your task.
The advice about using threads with GLib is probably also relevant here.
I have developed a code that is able to cancel a thread from another, both of them created from a main one. The code works correctly according to my tests:
#include <pthread.h>
#include <stdio.h>
/* these variables are references to the first and second threads */
pthread_t inc_x_thread, inc_y_thread;
/* this function is run by the first thread */
void *inc_x(void *x_void_ptr)
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
/* increment x to 100 */
int *x_ptr = (int *)x_void_ptr;
while(++(*x_ptr) < 100000000);
printf("x increment finished\n");
/* the function must return something - NULL will do */
return NULL;
}
/* this function is run by the second thread */
void *inc_y(void *x_void_ptr)
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
/* increment y to 100 */
int *x_ptr = (int *)x_void_ptr;
pthread_cancel(inc_x_thread);
while(++(*x_ptr) < 100);
printf("y increment finished\n");
return NULL;
}
/* this is the main thread */
int main()
{
int x = 0, y = 0;
void *res;
/* show the initial values of x and y */
printf("x: %d, y: %d\n", x, y);
/* create a first thread */
if(pthread_create(&inc_x_thread, NULL, inc_x, &x)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
/* create a second thread */
if(pthread_create(&inc_y_thread, NULL, inc_y, &y)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
/* wait for the first thread to finish */
if(pthread_join(inc_x_thread, &res)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
if (res == PTHREAD_CANCELED)
printf(" thread was canceled\n");
else
printf(" thread wasn't canceled\n");
/* wait for the second thread to finish */
if(pthread_join(inc_y_thread, &res)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
if (res == PTHREAD_CANCELED)
printf(" thread was canceled\n");
else
printf(" thread wasn't canceled\n");
/* show the results*/
printf("x: %d, y: %d\n", x, y);
return 0;
}
You can compile the code by using: gcc example.c -lpthread
However, as OznOg and Philip Withnall have said, this is not the correct way of cancelling a thread. It is only a quick way of doing it that might not work in some specific situations. A better and safer way is to gently ask the thread to stop itself.
I am doing multithreading in C++. This may be something very standard but I can't seem to find it anywhere or know any key terms to search for it online.
I want to do some sort of computation many times but with multiple threads. For each iteration of computation, I want to find the next available thread that has finished its previous computation to do the next iteration. I don't want to cycle through the threads in order since the next thread to be called may not have finished its work yet.
E.g.
Suppose I have a vector of int and I want to sum up the total with 5 threads. I have the to-be-updated total sum stored somewhere and the count for which element I am currently up to. Each thread looks at the count to see the next position and then takes that vector value and adds it to the total sum so far. Then it goes back to look for the count to do the next iteration. So for each iteration, the count increments then looks for the next available thread (maybe one already waiting for count; or maybe they are all busy still working) to do the next iteration. We do not increase the number of threads but I want to be able to somehow search through all the 5 threads for the first one that finish to do the next computation.
How would I go about coding this. Every way I know of involves doing a loop through the threads such that I can't check for the next available one which may be out of order.
Use semafor (or mutex, always mix up those two) on a global variable telling you what is next. The semafor will lock the other threads out as long as you access the variable making that threads access clear.
So, assuming you have an Array of X elements. And a global called nextfree witch is initalized to 0, then a psudo code would look like this:
while (1)
{
<lock semafor INT>
if (nextfree>=X)
{
<release semnafor INT>
<exit and terminate thread>
}
<Get the data based on "nextfree">
nextfree++;
<release semafor INT>
<do your stuff withe the chunk you got>
}
The point here is that each thread will be alone and have exlusive access to the data struct within the semafor lock and therefore can access the next available regardless of what the others doing. (The other threads will have to wait in line if they are done while another thread working on getting next data chunk. When you release only ONE that stands in queue will get access. The rest will have to wait.)
There are some things to be ware of. Semafor's might lock your system if you manage to exit in the wrong position (Withour releasing it) or create a deadlock.
This is a thread pool:
template<class T>
struct threaded_queue {
using lock = std::unique_lock<std::mutex>;
void push_back( T t ) {
{
lock l(m);
data.push_back(std::move(t));
}
cv.notify_one();
}
boost::optional<T> pop_front() {
lock l(m);
cv.wait(l, [this]{ return abort || !data.empty(); } );
if (abort) return {};
auto r = std::move(data.back());
data.pop_back();
return std::move(r);
}
void terminate() {
{
lock l(m);
abort = true;
data.clear();
}
cv.notify_all();
}
~threaded_queue()
{
terminate();
}
private:
std::mutex m;
std::deque<T> data;
std::condition_variable cv;
bool abort = false;
};
struct thread_pool {
thread_pool( std::size_t n = 1 ) { start_thread(n); }
thread_pool( thread_pool&& ) = delete;
thread_pool& operator=( thread_pool&& ) = delete;
~thread_pool() = default; // or `{ terminate(); }` if you want to abandon some tasks
template<class F, class R=std::result_of_t<F&()>>
std::future<R> queue_task( F task ) {
std::packaged_task<R()> p(std::move(task));
auto r = p.get_future();
tasks.push_back( std::move(p) );
return r;
}
template<class F, class R=std::result_of_t<F&()>>
std::future<R> run_task( F task ) {
if (threads_active() >= total_threads()) {
start_thread();
}
return queue_task( std::move(task) );
}
void terminate() {
tasks.terminate();
}
std::size_t threads_active() const {
return active;
}
std::size_t total_threads() const {
return threads.size();
}
void clear_threads() {
terminate();
threads.clear();
}
void start_thread( std::size_t n = 1 ) {
while(n-->0) {
threads.push_back(
std::async( std::launch::async,
[this]{
while(auto task = tasks.pop_front()) {
++active;
try{
(*task)();
} catch(...) {
--active;
throw;
}
--active;
}
}
)
);
}
}
private:
std::vector<std::future<void>> threads;
threaded_queue<std::packaged_task<void()>> tasks;
std::atomic<std::size_t> active;
};
You give it how many threads either at construction or via start_thread.
You then queue_task. This returns a std::future that tells you when the task is completed.
As threads finish a task, they go to the threaded_queue and look for more.
When a threaded_queue is destroyed, it aborts all data in it.
When a thread_pool is destroyed, it aborts all future tasks, then waits for all of the outstanding tasks to finish.
Live example.
I am creating a shell command from the custom shell to do the ssh from one terminal to another terminal.
In order to do the ssh, I am using the inbuilt ssh command of the linux. Here is my code that does the ssh login.
However, I am seeing that the I/O buffers are not in sync.
This is what I am seeing on the terminal. After SSH to the other terminal. I did the following in the terminal.
PRT# ssh 192.168.10.42
PRT# Could not create directory '/root/.ssh'.
root#192.168.10.42's password:
# screen -r
-sh: cen-: not found
# hello
-sh: el: not found
#
I don't what's the reason here. Here is the code.
int sshLogin(chr *destIp)
{
char cmd[CMD_LEN];
char readbuff[CMD_LEN];
pid_t pid;
int ret = 0;
int fd[2];
int result;
memset(cmd,'\0',sizeof(cmd));
int status = 0;
/** --tt required to force pseudowire allocation because we are behind screen app **/
sprintf(cmd,"/usr/bin/ssh -tt %s",destIp);
/** create a pipe this will be shared on fork() **/
pipe(fd);
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0 )
{
/** Child Process of Main APP --Make this parent process for the command**/
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0)
{
/** basically Main APP grand child - this is where we running the command **/
ret = execlp("ssh", "ssh", "-tt", destIp, NULL);
printf("done execlp\r\n");
}
else
{
/** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/
while( (read(fd[0], readbuff, sizeof(readbuff))))
{
printf("%s",readbuff);
}
waitpid(0,&status,0);
LOG_STRING("SSH CONNC CLOSED");
exit(0);
}
}
else
{
/** Parent process APP MAIN-- **/
/** no need to wait let APP MAIN run -- **/
}
return 0;
}
Based on Patrick Ideas.
POST 2# - It seems that it works when we close the stdin in the parent process. However, it becomes very slugguish, I feel like I am typing the keyboard too slow. The system becomes too sluggish. Also, I have a web-server from this terminal. I see that I can no longer access the web.
So, the solution is somewhere around stdin but I am not sure.
int sshLogin(chr *destIp)
{
char cmd[CMD_LEN];
char readbuff[CMD_LEN];
pid_t pid;
int ret = 0;
int fd[2];
int result;
memset(cmd,'\0',sizeof(cmd));
int status = 0;
/** --tt required to force pseudowire allocation because we are behind screen app **/
sprintf(cmd,"/usr/bin/ssh -tt %s",destIp);
/** create a pipe this will be shared on fork() **/
pipe(fd);
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0 )
{
/** Child Process of Main APP --Make this parent process for the command**/
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0)
{
/** basically Main APP grand child - this is where we running the command **/
ret = execlp("ssh", "ssh", "-tt", destIp, NULL);
printf("done execlp\r\n");
}
else
{
/** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/
while( (read(fd[0], readbuff, sizeof(readbuff))))
{
printf("%s",readbuff);
}
waitpid(0,&status,0);
LOG_STRING("SSH CONNC CLOSED");
exit(0);
}
}
else
{
/** Parent process APP MAIN-- **/
/** no need to wait let APP MAIN run -- **/
close(stdin);
}
return 0;
}
Basically, I have added - close(stdin);
You have 2 different processes trying to read from STDIN. This causes process 1 to get char 1, process 2 to get char 2, process 1 to get char 3, process 2 to get char 4, etc, alternating back and forth.
Your 2 processes are:
execlp("ssh", "ssh", "-tt", destIp, NULL);.
while( (read(fd[0], readbuff, sizeof(readbuff))))
Basically you need to ditch the read(fd[0],...).
My initial thought is that perhaps it is buffering the output: stdout is buffered, so unless you print a newline, nothing will be printed until a certain number of characters build up. This is because I/O operations are expensive. You can find more detail on this here. The result is that there is a delay because your program is waiting to print.
My suggestion: in your main function, before calling your sshLogin function, try disabling buffering with this line of code:
setbuf(stdout, NULL);
You can also call fflush(stdout); periodically to do the same thing, but the above method is more efficient. Try it and see if that solves your problem.
I'll preface this by saying that I'm delving into multithreading for the first time. Despite a lot of reading on concurrency and synchronization, I'm not readily seeing a solution for the requirements I've been given.
Using C++11 and Boost, I'm trying to figure out how to send data from a worker thread to a main thread. The worker thread is spawned at the start of the application and continuously monitors a lock free queue. Objects populate this queue at various intervals. This part is working.
Once the data is available, it needs to be processed by the main thread since another signal will be sent to the rest of the application which cannot be on a worker thread. This is what I'm having trouble with.
If I have to block the main thread through a mutex or a condition variable until the worker thread is done, how will that improve responsiveness? I might as well just stay with a single thread so I have access to the data. I must be missing something here.
I have posted a couple questions, thinking that Boost::Asio was the way to go. There is an example of how signals and data can be sent between threads, but as the responses indicate, things get quickly overly-complicated and it's not working perfectly:
How to connect signal to boost::asio::io_service when posting work on different thread?
Boost::Asio with Main/Workers threads - Can I start event loop before posting work?
After speaking with some colleagues, it was suggested that two queues be used -- one input, one output. This would be in shared space and the output queue would be populated by the worker thread. The worker thread is always going but there would need to be a Timer, probably at the application level, that would force the main thread to examine the output queue to see if there were any pending tasks.
Any ideas on where I should direct my attention? Are there any techniques or strategies that might work for what I'm trying to do? I'll be looking at Timers next.
Thanks.
Edit: This is production code for a plugin system that post-processes simulation results. We are using C++11 first wherever possible, followed by Boost. We are using Boost's lockfree::queue. The application is doing what we want on a single thread but now we are trying to optimize where we see that there are performance issues (in this case, a calculation happening through another library). The main thread has a lot of responsibilities, including database access, which is why I want to limit what the worker thread actually does.
Update: I have already been successful in using std::thread to launch a worker thread that examines a Boost lock::free queue and processes tasks placed it in. It's step 5 in #Pressacco's response that I'm having trouble with. Any examples returning a value to the main thread when a worker thread is finished and informing the main thread, rather than simply waiting for the worker to finish?
If your objective is develop the solution from scratch (using native threads, queues, etc.):
create a thread save queue queue (Mutex/CriticalSection around add/remove)
create a counting semaphore that is associated with the queue
have one or more worker threads wait on the counting semaphore (i.e. the thread will block)
the semaphore is more efficient than having the thread constantly poll the queue
as messages/jobs are added to the queue, increment the semaphore
a thread will wake up
the thread should remove one message
if a result needs to be returned...
setup another: Queue+Semaphore+WorkerThreads
ADDITIONAL NOTES
If you decide to implement a thread safe queue from scratch, take a look at:
Synchronization between threads using Critical Section
With that said, I would take another look at BOOST. I haven't used the library, but from what I hear it will most likely contain some relevant data structures (e.g. a thread safe queue).
My favorite quote from the MSDN:
"When you use multithreading of any sort, you potentially expose
yourself to very serious and complex bugs"
SIDEBAR
Since you are looking at concurrent programming for the first time, you may wish to consider:
Is your objective to build production worthy code , or is this simply a learning exercise?
production? consider us existing proven libraries
learning? consider writing the code from scratch
Consider using a thread pool with an asynchronous callback instead of native threads.
more threads != better
Are threads really needed?
Follow the KISS principle.
The feedback above led me in the right direction for what I needed. The solution was definitely simpler than having to use signals/slots or Boost::Asio as I had previously attempted. I have two lock-free queues, one for input (on a worker thread) and one for output (on the main thread, populated by the worker thread). I use a timer to schedule when the output queue is processed. The code is below; perhaps it is of use to somebody:
//Task.h
#include <iostream>
#include <thread>
class Task
{
public:
Task(bool shutdown = false) : _shutdown(shutdown) {};
virtual ~Task() {};
bool IsShutdownRequest() { return _shutdown; }
virtual int Execute() = 0;
private:
bool _shutdown;
};
class ShutdownTask : public Task
{
public:
ShutdownTask() : Task(true) {}
virtual int Execute() { return -1; }
};
class TimeSeriesTask : public Task
{
public:
TimeSeriesTask(int value) : _value(value) {};
virtual int Execute()
{
std::cout << "Calculating on thread " << std::this_thread::get_id() << std::endl;
return _value * 2;
}
private:
int _value;
};
// Main.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "afxwin.h"
#include <boost/lockfree/spsc_queue.hpp>
#include "Task.h"
static UINT_PTR ProcessDataCheckTimerID = 0;
static const int ProcessDataCheckPeriodInMilliseconds = 100;
class Manager
{
public:
Manager()
{
//Worker Thread with application lifetime that processes a lock free queue
_workerThread = std::thread(&Manager::ProcessInputData, this);
};
virtual ~Manager()
{
_workerThread.join();
};
void QueueData(int x)
{
if (x > 0)
{
_inputQueue.push(std::make_shared<TimeSeriesTask>(x));
}
else
{
_inputQueue.push(std::make_shared<ShutdownTask>());
}
}
void ProcessOutputData()
{
//process output data on the Main Thread
_outputQueue.consume_one([&](int value)
{
if (value < 0)
{
PostQuitMessage(WM_QUIT);
}
else
{
int result = value - 1;
std::cout << "Final result is " << result << " on thread " << std::this_thread::get_id() << std::endl;
}
});
}
private:
void ProcessInputData()
{
bool shutdown = false;
//Worker Thread processes input data indefinitely
do
{
_inputQueue.consume_one([&](std::shared_ptr<Task> task)
{
std::cout << "Getting element from input queue on thread " << std::this_thread::get_id() << std::endl;
if (task->IsShutdownRequest()) { shutdown = true; }
int result = task->Execute();
_outputQueue.push(result);
});
} while (shutdown == false);
}
std::thread _workerThread;
boost::lockfree::spsc_queue<std::shared_ptr<Task>, boost::lockfree::capacity<1024>> _inputQueue;
boost::lockfree::spsc_queue<int, boost::lockfree::capacity<1024>> _outputQueue;
};
std::shared_ptr<Manager> g_pMgr;
//timer to force Main Thread to process Manager's output queue
void CALLBACK TimerCallback(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
if (nIDEvent == ProcessDataCheckTimerID)
{
KillTimer(NULL, ProcessDataCheckPeriodInMilliseconds);
ProcessDataCheckTimerID = 0;
//call function to process data
g_pMgr->ProcessOutputData();
//reset timer
ProcessDataCheckTimerID = SetTimer(NULL, ProcessDataCheckTimerID, ProcessDataCheckPeriodInMilliseconds, (TIMERPROC)&TimerCallback);
}
}
int main()
{
std::cout << "Main thread is " << std::this_thread::get_id() << std::endl;
g_pMgr = std::make_shared<Manager>();
ProcessDataCheckTimerID = SetTimer(NULL, ProcessDataCheckTimerID, ProcessDataCheckPeriodInMilliseconds, (TIMERPROC)&TimerCallback);
//queue up some dummy data
for (int i = 1; i <= 10; i++)
{
g_pMgr->QueueData(i);
}
//queue a shutdown request
g_pMgr->QueueData(-1);
//fake the application's message loop
MSG msg;
bool shutdown = false;
while (shutdown == false)
{
if (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
shutdown = true;
}
}
return 0;
}
I've just started with learning MFC and I'm writing one dialog based application for better understanding of Multi-Threading.
The main dialog has a progress bar, a Start button and a Cancel button.
On click of the start button, i'm creating a worker thread to do some processing(through API call) and the main thread takes care of Progress bar.
I've defined a couple of Windows Messages to update and stop Progress bar status
WM_UPDATE_CONTROL
WM_STOP_CONTROL
Below is the code that i've created so far
HWND* phObjectHandle;
CWinThread* thread;
void CprogCtrlDlg::OnBnClickedStart() {
phObjectHandle = new HWND; // Set object handle for Worker thread
*phObjectHandle = GetSafeHwnd();
// create worker thread
if(NULL == (thread = AfxBeginThread(ThreadFunc, phObjectHandle))) {
EndDialog(IDCANCEL);
}
AfxMessageBox(L"Thread started");
// Set Progress bar to marquee
}
void CprogCtrlDlg::OnBnClickedCancel() {
// kill the Worker thread
}
UINT CprogCtrlDlg::ThreadFunc(LPVOID pParam) {
HWND *pObjectHandle = static_cast<HWND *>(pParam);
CprogCtrlImpDlg* threadDlg = (CprogCtrlImpDlg*) pParam;
return threadDlg->ThreadFuncRun(pObjectHandle);
}
UINT CprogCtrlDlg::ThreadFuncRun(HWND* pObjectHandle) {
::PostMessage(*pObjectHandle, WM_UPDATE_CONTROL, 0, 0);
// repetitive API CALL in a loop
::PostMessage(*pObjectHandle, WM_STOP_CONTROL, 0, 0);
AfxMessageBox(L"Thread completed");
return 0;
}
I want to terminate the Worker thread from a Parent thread, if a Cancel button is clicked.
I tried using TerminateThread()(though it wasn't a suggested one) but I couldn't kill the thread.
Please comment and share your thoughts on terminating a worker thread from a parent thread.
I'm using visual studio 2010 on Windows 7
TIA
I would amend your code something like this.
Have some member variables in your dialog class to hold the thread handle and an event handle (initialise to NULL in the constructor):
CWinThread* m_hThread;
HANDLE m_hKillEvent;
Use a static function as your thread entry point, pass the dialog this as the parameter, then delegate the call back to the class instance so you have access to all of the dialog's variables:
UINT ThreadFunc(LPVOID pParam)
{
// static thread func - delegate to instance
CprogCtrlDlg* pDlg = static_cast<CprogCtrlDlg*>(pParam);
return pDlg->ThreadFuncRun();
}
When you start the thread, create an event too:
void CprogCtrlDlg::OnBnClickedStart()
{
// create worker thread
m_hKillEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hThread = AfxBeginThread(ThreadFunc, this);
AfxMessageBox(L"Thread started");
}
To kill the thread, just set the event and wait on the thread handle, which will get signaled on death:
void CprogCtrlDlg::OnBnClickedCancel()
{
// kill the Worker thread
SetEvent(m_hKillEvent);
// wait for it to die
DWORD dwRet = WaitForSingleObject(m_hThread->m_hThread, 5000);
if (dwRet == WAIT_TIMEOUT)
{
// thread failed to die after 5 seconds
// error handling (maybe TerminateThread here)
}
}
In the thread function (now in the dialog class) you can post messages to yourself to indicate progress and use a wait on the event to catch a kill request:
UINT CprogCtrlDlg::ThreadFuncRun()
{
// instance thread func
PostMessage(WM_UPDATE_CONTROL, 0, 0);
// main loop
while (true)
{
// check kill
DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0);
if (dwRet == WAIT_OBJECT_0) break;
// do a little work here and update progress
// ... so this is part of your working loop ...
PostMessage(WM_UPDATE_CONTROL, 0, 1 /*2,3,4,...*/);
}
// normal thread exit
PostMessage(WM_STOP_CONTROL, 0, 0);
return 0;
}
I've left out initialisation, cleanup of pointers, handles etc. but you get the general idea I hope.
There are several ways you can code the thread loop, you can do it like above where you periodically check to see if the event is signaled, or you can wait on the event to get signaled to do the work. Both are common patterns and often used together with two events - one for triggering work and the other for killing. See this answer for some important points to note if waiting on multiple events.
For a simple progress bar update, you can put the event check inside the work loop, something like this:
UINT CprogCtrlDlg::ThreadFuncRun()
{
// instance thread func
PostMessage(WM_UPDATE_CONTROL, 0, 0);
// main loop
for (int i = 0; i < 100; ++i)
{
// check kill
DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0);
if (dwRet == WAIT_OBJECT_0) break;
// do a little work here and update progress
PostMessage(WM_UPDATE_CONTROL, 0, (LPARAM)i);
}
// normal thread exit
PostMessage(WM_STOP_CONTROL, 0, 0);
return 0;
}