I am relatively new to working with threads in Win32 api and have reached a problem that i am unable to work out.
Heres my problem, i have 4 threads (they work as intended) that allow the operator to test 4 terminals. In each thread i am trying to send a message to the main windows form with either Pass or Fail, this is placed within a listbox. Below is one of the threads, the remaining are exactly the same.
void Thread1(PVOID pvoid)
{
for(int i=0;i<numberOfTests1;i++) {
int ret;
double TimeOut = 60.0;
int Lng = 1;
test1[i].testNumber = getTestNumber(test1[i].testName);
unsigned char Param[255] = {0};
unsigned char Port1 = port1;
ret = PSB30_Open(Port1, 16);
ret = PSB30_SendOrder (Port1, test1[i].testNumber, &Param[0], &Lng, &TimeOut);
ret = PSB30_Close (Port1);
if(*Param == 1) SendDlgItemMessage(hWnd,IDT_RESULTLIST1,LB_ADDSTRING,i,(LPARAM)"PASS");
else SendDlgItemMessage(hWnd,IDT_RESULTLIST1,LB_ADDSTRING,i,(LPARAM)"FAIL");
}
_endthread();
}
I have debugged the code and it does everything except populate the listbox, i assume because its a thread i am missing something as the same code works outwith the thread. Do i need to put the thread to sleep while it sends the message to the main window?
Any help is appreciated.
Cheers
You don't want your secondary threads trying to manipulate your UI elements directly (such as the SendDlgItemMessage). Instead, you normally want to post something like a WM_COMMAND or WM_USER+N to the main window, and let that manipulate the UI elements accordingly.
Related
I have the following code which I am trying to run, however the wait_for_connection() appears to be being run before the preceding 2 lines, and I can't seem to understand why? I really need the two preceding lines to be run before the wait_for_connection() function is called. Even if I enter a sleep(1) before calling the wait_for_connection() function, it is still run before the preceding lines.
My code is as follows:
void wait_for_connection() {
for (int i = 0; i < 10; i++) {
g_print("Checking server...\n");
if (connected == 1) {
g_print("Connected to: %s", selectedServerStr);
break;
}
sleep(1);
}
}
int connect_server(GtkButton *button, gpointer user_data) {
.......
if (gtk_tree_selection_get_selected(GTK_TREE_SELECTION(selectedServer), &model, &iter)) {
path = gtk_tree_model_get_path(model, &iter);
serverIndex = *gtk_tree_path_get_indices(path);
g_print("Selected Server IP: %s\n", serverIPArray[serverIndex][0]);
gtk_widget_set_sensitive(serverList, FALSE); // These 2 lines needs to be run first
append_to_log("Attemping connection, please wait...", 1);
wait_for_connection(); // This is where the error lies, this runs before the above 2 lines
return 1;
} else {
gtk_widget_set_name(serverBox, "fieldsError");
g_print("No server selected: Aborting...\n");
return -1;
}
}
The line gtk_widget_set_sensitive() is used to disable user interaction of a selection widget, however this doesn't seem to happen until after the wait_for_connection() function has finished printing "Checking server..." 10 times. The value connected is 0, so currently the function just print "Checking server..." 10 times.
Does anyone have any idea as to what may be happening? Any help would be greatly appreciated, thanks.
GUI applications on almost all platforms are event-driven. They need their event-handling functions to execute at regular interval, or the user-interface will seem unresponsive and maybe even seem like it locks up or nothing is happening.
In your wait_for_connection you have a loop which can iterate up to ten times, and each iteration you will do sleep(1) which sleeps a whole second. While this loop is iterating and sleeping, the event-handling will not happen, and as mentioned that will make it seem like your user-interface is unresponsive and doesn't do anything.
You need to modify your code to be event-driven as well, so the "connection" status will be sent as an event that you can handle, or somehow make the polling asynchronous so it happens in parallel to the event-handling.
I'm making a GTK+3 application in C and I want a spinner to show when the program is processing the data. Here's what I generally have:
main()
{
//Some statements
g_signal_connect(G_OBJECT(btnGenerate), "clicked", G_CALLBACK(Generate), &mainform);
}
void Generate(GtkWidget *btnGenerate, form_widgets *p_main_form)
{
gtk_spinner_start(GTK_SPINNER(p_main_form->spnProcessing));
Begin_Lengthy_Processing(Parameters, Galore, ...);
//gtk_spinner_stop(GTK_SPINNER(p_main_form->spnProcessing));
}
I have the stop function commented out so I can see the spinner spin even after the function has finished, but the spinner starts after the function is finished, and I suspect it turns on in the main loop.
I also found out that the entire interface freezes during the execution of the long going function.
Is there a way to get it to start and display inside the callback function? I found the same question, but it uses Python and threads. This is C, not Python, so I would assume things are different.
You need to run your lengthy computation in a separate thread, or break it up into chunks and run each of them separately as idle callbacks in the main thread.
If your lengthy computation takes a single set of inputs and doesn’t need any more inputs until it’s finished, then you should construct it as a GTask and use g_task_run_in_thread() to start the task. Its result will be delivered back to the main thread via the GTask’s GAsyncReadyCallback. There’s an example here.
If it takes more input as it progresses, you probably want to use a GAsyncQueue to feed it more inputs, and a GThreadPool to provide the threads (amortising the cost of creating threads over multiple calls to the lengthy function, and protecting against denial of service).
The GNOME developer docs give an overview of how to do threading.
This is what I got:
int main()
{
// Statements...
g_signal_connect(G_OBJECT(btnGenerate), "clicked", G_CALLBACK(Process), &mainform);
// More statements...
}
void Process(GtkWidget *btnGenerate, form_widgets *p_main_form)
{
GError *processing_error;
GThread *start_processing;
gtk_spinner_start(GTK_SPINNER(p_main_form->spnProcessing));
active = true;
if((start_processing = g_thread_try_new(NULL, (GThreadFunc)Generate, p_main_form, &processing_error)) == NULL)
{
printf("%s\n", processing_error->message);
printf("Error, cannot create thread!?!?\n\n");
exit(processing_error->code);
}
}
void Generate(form_widgets *p_main_form)
{
// Long process
active = false;
}
My program, once cleaned up and finished, as there are many other bugs in the program, will be put on GitHub.
Thank you all for your help. This answer comes from looking at all of your answers and comments as well as reading some more documentation, but mostly your comments and answers.
I did something similar in my gtk3 program. It's not that difficult. Here's how I would go about it.
/**
g_idle_add_full() expects a pointer to a function with the signature below:
(*GSourceFunc) (gpointer user_data).
So your function signature must adhere to that in order to be called.
But you might want to pass variables to the function.
If you don't want to have the variables in the global scope
then you can do this:
typedef struct myDataType {
char* name;
int age;
} myDataType;
myDataType person = {"Max", 25};
then when calling g_idle_add_full() you do it this way:
g_idle_add_full(G_PRIORITY_HIGH_IDLE, myFunction, person, NULL);
*/
int main()
{
// Assumming there exist a pointer called data
g_idle_add_full(G_PRIORITY_HIGH_IDLE, lengthyProcessCallBack, data, NULL);
// GTK & GDK event loop continues and window should be responsive while function runs in background
}
gboolean lengthyProcessCallBack(gpointer data)
{
myDataType person = (myDataType) *data;
// Doing lenghthy stuff
while(;;) {
sleep(3600); // hypothetical long process :D
}
return FALSE; // removed from event sources and won't be called again.
}
Are users of GLib allowed to run multiple GMainLoop instances concurrently in multiple threads, with each thread running its own instance? I've found "yes" and "no" answers all over the place. I realize that this question has been asked before in this very forum (December 2011).
However, I am able to run two GMainLoop instances at the same time without apparent issue. My test code is very simple:
Create a GMainLoop in main()
Create a timeout source for the default context and the main loop using g_timeout_add
Create a GThread in main()
Run the main loop using g_main_loop_run
[THREAD CONTEXT]: Create a context using g_main_context_new
[THREAD CONTEXT]: Set that context as the thread default using g_main_context_push_thread_default
[THREAD CONTEXT]: Create a loop using g_main_loop_new and give it the new context
[THREAD CONTEXT]: Create a timeout source, and attach it to the new context via g_source_attach.
[THREAD_CONTEXT]: Have the thread invoke g_main_loop_run
Doing this, I see both instances of the GMainLoop working just fine. The timeout callbacks are invoked correctly, and later calls to g_main_loop_quit work as expected.
So, it looks like it is not a problem to have multiple GMainLoop instances working concurrently. But perhaps I just haven't exercised the API enough to fully grasp the situation. Is there a definitive answer to this question?
Also, here's the actual test code if anybody cares to look:
#define THREAD_TIMEOUTS (20)
#define MAIN_TIMEOUS (1)
typedef struct timeout_struct
{
int i;
int max;
GMainLoop *loop;
char *name;
} TIMEOUT_STRUCT;
gboolean timeout_callback(gpointer data)
{
TIMEOUT_STRUCT *psTimeout = (TIMEOUT_STRUCT *)data;
psTimeout->i++;
if (psTimeout->i == psTimeout->max)
{
if (psTimeout->max == THREAD_TIMEOUTS)
{
g_main_loop_quit( (GMainLoop*)psTimeout->loop );
}
return FALSE;
}
return TRUE;
}
void* thread_function(void *data)
{
GMainContext *ps_context;
GMainLoop *ps_loop;
GSource *ps_timer;
TIMEOUT_STRUCT sTimeout;
ps_context = g_main_context_new();
g_main_context_push_thread_default(ps_context);
ps_loop = g_main_loop_new(ps_context, FALSE);
sTimeout.i = 0;
sTimeout.max = THREAD_TIMEOUTS;
sTimeout.loop = ps_loop;
sTimeout.name = "thread";
ps_timer = g_timeout_source_new_seconds(1);
g_source_set_callback(ps_timer, timeout_callback, &sTimeout, NULL);
g_source_attach(ps_timer, ps_context);
g_main_loop_run(ps_loop);
g_main_loop_quit( (GMainLoop*)data );
return NULL;
}
/*
* This main boots a thread, then starts up a GMainLoop. Then the thread runs
* a GMainLoop. The thread sets a timer that fires ten times and the main sets a
* timer that fires two times. The thread quits and
* and then the other main l
*
*
* */
int main()
{
GThread *ps_thread;
GMainLoop *loop;
TIMEOUT_STRUCT sTimeout;
loop = g_main_loop_new ( NULL , FALSE );
sTimeout.i = 0;
sTimeout.max = MAIN_TIMEOUS;
sTimeout.loop = loop;
sTimeout.name = "main";
// add source to default context
g_timeout_add (1 , timeout_callback, &sTimeout);
ps_thread = g_thread_new("thread", thread_function, loop);
g_main_loop_run (loop);
g_main_loop_unref(loop);
}
The book "Foundations of GTK+ Development" states this:
The GLib main loop is implemented as a number of structures, which allow multiple instances
to be run concurrently.
So, given this, my test code, and the link I posted in the comment above we have a definitive answer to this question.
Namely: Multiple threads may have their own GMainContext & GMainLoop, and are able to independently run these loops in a concurrent fashion.
I'm running into a bit of trouble with C. I'm a relatively new programmer and I'm trying to create a structure and pass it into two thread by reference. I want one thread to put information into the structure and the other thread to add the information and print it out. Pseudo-code of what I'm talking about is below:
typedef struct{ int x, y }addme;
main{
addme argstopass;
create_thread(method_store, (void*)&argstopass);
create_thread(method_calc, (void*)&argstopass);
//Code to tell store thread 'only' to run
//Code to tell calc thread to run when store is finished.
join_both_threads;
}
void method_store(void* args){
addme info = *((addme*)args);
info.a = 7;
info.b = 3;
}
void method_calc(void* args){
addme info = *((addme*)args);
print(info.a+info.b);
}
The issue is that when I try to add the information it's like the store method had never updated it. The reference passed into the threads is the same, so I can't see why they wouldn't be able to access the same information as long as they both have a pointer to it.
Hopefully someone here can enlighten me as to what I'm doing wrong. If anything isn't clear, comment and I'll help to clarify.
addme info = *((addme*)args);
creates a locale variable on stack and copies content of argstopass into it. Modifications happen on this local variable only and won't be seen by the second thread hence.
Use
addme *info = args;
info->a = 7;
and ditto for the second thread. You will have to ensure that second thread waits with its printf() until first thread modified the values.
void method_store(void* args){
addme info = *((addme*)args);
info.a = 7;
info.b = 3;
}
This method creates a local copy of your structure field, updates that local copy, and then returns, destroying the copy and not doing anything to your main structure.
I am migrating some code of CYBOI from Xlib to XCB.
CYBOI uses a couple of threads for different communication channels like:
serial_port, terminal, socket, x_window_system.
However, it uses these threads only for signal/event/data detection;
the actual receiving and sending is done in the main thread,
in order to avoid any multi-threading conflicts of address space.
For the x_window_system channel, I previously detected events in a thread:
int n = XEventsQueued(display, QueuedAfterReading);
Upon detection of an event, an "interrupt flag" was set.
Afterwards, the main thread was reading the actual event using:
XNextEvent(display, &event);
When no more events were available, the main thread stopped receiving events
and the x_window_system channel thread started listening with XEventsQueued again.
Now, I am migrating the code to X C Binding (XCB).
There is a blocking function "xcb_wait_for_event" which is fine for reading an event.
What I miss is some function "peeking ahead" if there are events pending,
WITHOUT actually returning/removing the event from the queue.
I was reading the web for a couple of hours now, but am not able to find such a function.
The "xcb_poll_for_event" does not help. Blocking is fine for me,
since my event detection runs in its own thread.
The "xcb_request_check" as third input function does not seem to be what I want.
Could somebody help me out?
Thanks,
Christian
Are you looking for xcb_poll_for_queued_event(xcb_connection_t *c) which returns the next event without reading from the connection?
First, thanks to Julien for his reply.
I have studied the XCB 1.9 sources and found out that the
"xcb_poll_for_queued_event" function is not what I need.
The functions "xcb_poll_for_event" and "xcb_poll_for_queued_event"
both call "poll_for_next_event".
The functions "poll_for_next_event" and "xcb_wait_for_event"
both call "get_event".
If "get_event" finds an event, it changes the internal
linked list to point to the next event. However, I would
prefer NOT to change the event queue AT ALL, independent
from whether or not events are available.
I therefore propose to add a function like the following to XCB:
void* NULL_POINTER = (void*) 0;
int xcb_test_for_event(xcb_connection_t* c) {
int r = 0;
if (c != NULL_POINTER) {
struct _xcb_in in = c->in;
struct event_list* l = in.events;
if (l != NULL_POINTER) {
xcb_generic_event_t* e = l->event;
if (e != NULL_POINTER) {
r = 1;
}
}
}
return r;
}
This would allow me to write an endless loop like:
while (!xcb_test_for_event(connection)) {
sleep(t);
}
This is comparable to the old Xlib function:
int n = XEventsQueued(d, QueuedAfterReading);
which just checked the number of events in the event queue.
The "XEventsQueued" function always returns immediately WITHOUT
input/output, if there are events already in the queue.
Thanks
Christian