0
static DWORD WINAPI puneWeather()
{
    float c1_temp=0.0;
    srand(rand());
    c1_temp = float(22.3+static_cast<float>(rand()/static_cast<float>(RAND_MAX/(30.1-22.3)))); 
    return c1_temp;
}

void CWeatherAppDlg::OnBnClickedRunallBtn()
{
    HANDLE city1;
    city1 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&CWeatherAppDlg::puneWeather,NULL,0,NULL);
}

How can I get the value that the function puneweather returns, after the function is called from createthread()? Is this possible?

I have started learning C++ a week ago. Please point out any noob mistakes.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
Shlok Jaiswal
  • 13
  • 1
  • 6
  • a simple alternative is use callback or set global variable. – apple apple Jan 05 '18 at 06:43
  • You need to tell us what you're _actually_ trying to achieve. The code you show here makes absolutely no sense. It's totally pointless to create a thread here. Read this: [The XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Jabberwocky Jan 05 '18 at 08:24
  • 1
    Noob mistakes: Casting the function pointer hides the compiler error, because your [thread proc](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686736.aspx) has the wrong signature. Don't use `CreateThread`, when you plan to call into the CRT from the thread proc (you are). Use `_beginthreadex` instead. Both of these are *clearly* documented. Next noob mistake: Ignoring compiler warnings. You are truncating a `float`, stuffing it into a `DWORD`. Nothing good will come of this. You need to stop guessing. Get a few decent books on C++, read, and comprehend them. – IInspectable Jan 05 '18 at 12:56
  • 1
    What you are trying to do in technical terms is not possible but if you tell us what you really want to do with return value, then there is probably a better way. – zar Jan 05 '18 at 19:13
  • @IInspectable okay thankyou. will look into this. – Shlok Jaiswal Jan 08 '18 at 04:17
  • @MichaelWalz I am trying to create an MFC dialog based application in which there are 4 buttons which upon click display the weather of a particular city in their own text boxes. Then i want to create a fifth button which upon click will display display the weather of all the cities continuously. – Shlok Jaiswal Jan 08 '18 at 04:24
  • @zar I am trying to create an MFC dialog based application in which there are 4 buttons which upon click display the weather of a particular city in their own text boxes. Then i want to create a fifth button which upon click will display display the weather of all the cities continuously. I was hoping if i can get the return value from my weather functions by calling them using threads and then set that value in the individual text boxes of the cities. – Shlok Jaiswal Jan 08 '18 at 04:26
  • @IInspectable can you please recommend some good books for c++? – Shlok Jaiswal Jan 08 '18 at 04:28
  • [The Definitive C++ Book Guide and List](https://stackoverflow.com/q/388242/1889329). – IInspectable Jan 08 '18 at 10:08
  • You don't need thread for this but if you are doing this for learning purposes, use the approach I described in my answer. But its more complicated than my answer since you are monitoring, as oppose to one specific task and ending the thread. – zar Jan 08 '18 at 18:58
  • @zar thank you sir. – Shlok Jaiswal Jan 09 '18 at 04:18
  • @IInspectable Thank you sir. – Shlok Jaiswal Jan 09 '18 at 04:18

3 Answers3

1

The documentation for ThreadProc says this:

A process can determine when a thread it created has completed by using one of the wait functions. It can also obtain the return value of its ThreadProc by calling the GetExitCodeThread function.

So you call WaitForSingleObject or one of the other wait functions to wait for the thread to complete. Once you know that it is complete you call GetExitCodeThread to obtain the thread procedure's return value.

Note also that the documentation for ThreadProc gives this as the signature for the function:

DWORD WINAPI ThreadProc(
  _In_ LPVOID lpParameter
);

Your function does not have this signature, having omitted the lpParameter argument. Because of this, the compiler would have objected to you passing a function pointer with the wrong signature. Instead of correcting the signature you chose to suppress the compiler error by using a cast to LPTHREAD_START_ROUTINE.

This is a very bad habit to get into. Don't tell lies like this to the compiler. Simply fix the declaration of your thread procedure:

static DWORD WINAPI puneWeather(LPVOID lpParameter)

And then the expression to the right hand side of the assignment to c1_temp looks utterly bogus. I really don't know what you are trying to achieve there, but for sure that's not the solution to any problem!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    You already know this, but OP propably not. `WaitForSingleObject` will stall the UI thread, making the UI appear unresponsive. A common pattern to avoid that is to `PostMessage()` an application-defined (`WM_APP+x`) message from the worker thread to the UI thread just before the worker thread returns. In the handler of that message it is OK to call `WaitForSingleObject` because we already know that the wait duration will be very short. – zett42 Jan 05 '18 at 10:13
  • @DavidHeffernan can we use any other type of variable than LPDWORD to keep the exit code? – Shlok Jaiswal Jan 09 '18 at 06:09
  • Well, the return code is a DWORD. You can't change that. – David Heffernan Jan 09 '18 at 08:00
1

You are essentially wanting your thread to return value but threads don't work this way. Threads are asynchronous, they can take any amount of time depending on what they are doing and finish. Caller thread typically doesn't wait for it to get back the result.

The right option in this case is for your thread to PostMessage() to your main thread or the main window with the value it wants to pass when it has results available.

You can pass this thread the HWND of main window and PostMessage()to this window to pass results back.

zar
  • 11,361
  • 14
  • 96
  • 178
-3

Use a static variable and assign the value from the thread, then access it from the place you need it.

static float sResult;
static DWORD WINAPI puneWeather()
    {
        float c1_temp = 0.0;
        srand(rand());
        c1_temp = float(22.3 + static_cast<float>(rand() / static_cast<float>(RAND_MAX / (30.1 - 22.3))));
        sResult  = c1_temp;
        return 0;
    }

    int main()
    {
        HANDLE city1;
        city1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&puneWeather, NULL, 0, NULL);
        WaitForSingleObject(city1, INFINITE);
        printf("puneWeather return %f \n", sResult);
        return 0;
    }
Robinson
  • 185
  • 1
  • 4
  • 2
    Kinda lame. Imagine if two such threads were created. You also reproduce the bogus cast to `LPTHREAD_START_ROUTINE`. Note that `puneWeather` has the wrong signature and the cast simply tells a big fat lie to the compiler. – David Heffernan Jan 05 '18 at 09:33