Returning Value from Thread

Returning value from Thread

Usually you would do it something like this

 public class Foo implements Runnable {
private volatile int value;

@Override
public void run() {
value = 2;
}

public int getValue() {
return value;
}
}

Then you can create the thread and retrieve the value (given that the value has been set)

Foo foo = new Foo();
Thread thread = new Thread(foo);
thread.start();
thread.join();
int value = foo.getValue();

tl;dr a thread cannot return a value (at least not without a callback mechanism). You should reference a thread like an ordinary class and ask for the value.

How to get the return value from a thread in Python?

In Python 3.2+, stdlib concurrent.futures module provides a higher level API to threading, including passing return values or exceptions from a worker thread back to the main thread:

import concurrent.futures

def foo(bar):
print('hello {}'.format(bar))
return 'foo'

with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(foo, 'world!')
return_value = future.result()
print(return_value)

How to get a return value from a thread?

For obtaining return values form functions that are meant to be run in background, you may want to consider std::future instead of directly creating an std::thread object. You can use the std::async() function template to start an asynchronous task. It returns an std::future object that will eventually contain the return value of the function passed:

auto res = std::async(fun);

// ... optionally do something else

std::cout << res.get() << '\n';

That is, you create an std::future<int> by calling std::async(func). Then, when you need fun()'s return value, you simply call the get() member function on the future. If the future isn't ready yet (i.e., if it doesn't have the result yet), then the thread will block until it is.


Why not directly use std::thread

The problem with std::thread is that it doesn't provide a direct mechanism for transferring the return value of the callable passed at its construction. For example, suppose you want to start a new thread with std::thread to calculate the sum of two integers with the following function:

int sum(int a, int b) { return a + b; }

What you would probably try is:

std::thread th_sum(sum, 1, 2);

// ... optionally do something else

th_sum.join();
// calculation is finished, but where is the result?

The thread represented by th_sum does calculate the sum of 1 and 2. However, you don't get sum()'s return value, i.e., the result, from the associated std::thread object.

Instead, what you could do to handle this deficiency is, for example, to create a wrapper function for sum() that has an out parameter for the result instead of returning it:

void sum_outparam(int a, int b, int& res) { res = sum(a, b); }

Then, you can start a new thread for running this wrapper function and with help of std::ref() you will obtain the result in res:

int res;
std::thread th_sum(sum_outparam, 1, 2, std::ref(res));

// ... optionally do something else


th_sum.join();
// now, res contains the result

How to return value from thread (java)

Or simply add

...
a.start();
a.join(); // Add this
...

to wait for the thread to finish before getting the result.

Your problem is that you're trying to get the result before it has been calculated. You should wait for the thread to finish before getting the result. This answer is perhaps not the best but is the simplest. As other people had already used the Executors class I didnt want to repeat their answers. I would, however, familiarise yourself with Thread and its methods before moving onto Executors to help you get a better understanding of threads as, from your post, it appears you may be a novice in this area.

Thanks to l4mpi (on the meta site) for pointing out the lack of explanation.

Returning values from thread

Your code, in general, seems pretty solid, but there are several problems.
The task you created does the trick, and the progress bar will work, but it uses a thread so returning that the tests are complete without confirming the progress of the thread is wrong. Because the tests are in a thread and the method returns a value without being dependent on it, the value is returned before the tests are done.
When calling thread.start() the thread starts execution seperatly from your current thread, meaning that your code continues to execute as usual even if the thread was not done.

You have 2 possible options: keep the thread, or don't. If you don't keep the thread, that means that the tests are executed in the method which causes the javaFX event that called it to wait for the tests to finish. This is a bad idea because now the javaFX thread is stuck and the window can't handle any other events (basically, iresponsive).

A good option is to keep the thread, only that at the end of the thread you could show a dialog indicating whether the tests were complete or not. To do that you can use Platform.runLater(runnable) and pass it a Runnable object which shows the dialog:

Platform.runLater(()->{
//show dialog
});

It is required because you can't show a dialog while not in the javaFX thread. This allows you to run something in the javaFX thread.

Another issue is the fact that you're accessing the files outside of your thread. Meaning that at the same time the thread runs your test, you attempt to access the files and write to them. Instead of doing that, you should either write to the file in the thread or before it is started.

To summerize it all, you should use your thread to execute the tests and show the dialogs which indicate whether or not the tests were completed. Writing to your test file should not be done while the thread is still executing tests, but rather after the thread was finished, so you can do it at the end of the task.

public void runTests(){
if(testsRunning) return;

testsRunning = true;

final Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
FileInputStream fis = null;
File testDataFile = null;
try {
fis = new FileInputStream(selectedTestDataFile);
} catch (FileNotFoundException e) {
displayResponse("File Input Stream Error: File Not Found");
}

// Finds the workbook instance for XLSX file
XSSFWorkbook myWorkBook = null;
try {
myWorkBook = new XSSFWorkbook(fis);
} catch (IOException e) {
displayResponse("XSSFWorkbook I/O Error");
}

// displayResponse(first sheet from the XLSX workbook
XSSFSheet mySheet = myWorkBook.getSheetAt(0);

int totalWids = mySheet.getLastRowNum();

for (int rowIndex = 1; rowIndex <= totalWids; rowIndex++) {
updateProgress(rowIndex, totalWids);
Row row = mySheet.getRow(rowIndex);
if (row != null) {
String data = "");

Cell cellData = row.getCell(2);

if (cellData != null) {
data = cellWid.getStringCellValue();
boolean testresult = runTest(data);
System.out.println(rowIndex + ". data = " + data + ", testresult = " + testresult);
}
}
}

/* xlsx read */
FileOutputStream fos = null;
try {
fos = new FileOutputStream(selectedTestDataFile);
} catch (FileNotFoundException e) {
try {
myWorkBook.close();
} catch (IOException e1) {
displayResponse("Error: Please Close Workbook");
}
displayResponse("Error: File Not Found");
}
try {
myWorkBook.write(fos);
} catch (IOException e) {
try {
myWorkBook.close();
} catch (IOException e1) {
displayResponse("Error: Please Close Workbook");
}
displayResponse("Error: Workbook Write");
}
try {
fos.close();
} catch (IOException e) {
try {
myWorkBook.close();
} catch (IOException e1) {
displayResponse("Error: Please Close Workbook");
}
displayResponse("Error: File Output Stream");
}
try {
myWorkBook.close();
} catch (IOException e) {
displayResponse("Error: Please Close Workbook");
}
try {
fis.close();
} catch (IOException e) {
displayResponse("Error: Input file format");
}

displayResponse("Testing Complete!");

return null;
}
private void displayResponse(String testResultMessage){
Platform.runLater(()->{
if (testResultMessage.equals("Testing Complete!")) {
Alert alert = DialogUtils.getAlert("Info", "Information", testResultMessage, "info");
alert.showAndWait();

} else {
Alert alert = DialogUtils.getAlert("Error", "Error(s)", testResultMessage, "error");
alert.showAndWait();
}
testsRunning = false;
});
}
};

progressBar.progressProperty().bind(task.progressProperty());
progressIndicator.progressProperty().bind(task.progressProperty());

final Thread thread = new Thread(task, "task-thread");
thread.setDaemon(true);
thread.start();
}

So this code now does everything test related in the thread and doesn't interrupt your window from handling events. There is one problem from this: someone might press the runTests button again, while the tests are running. One option is to use a boolean indicating whether the tests are already active and check its value when runTests is called which I added and is called testsRunning. displayResponse is called when the tests where finished (completed or not) and it displayes the response dialog.

Hope I helped, and sorry for the long answer.

How to return Value from Multi Threading?

In multi threaded environment, we can return the values from thread by using Executer Service. This feature is available from JDK 5.

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html

Example :

public class MyThread implements Callable{

@Override
public String call(){
Thread.sleep(2000);
return "Hello";
}

public static void main(String args[]){
ExecutorService executor = Executors.newFixedThreadPool(5);
Callable<String> callable = new MyThread();
String value = executor.submit(callable);
System.out.println("The returned value is : "+value);
executor.shutdown();
}

}

This is the way you can return the values from thread.

Can one retrieve the return value of a thread function in C++11?

You can follow this sample code to get the return value from a thread :-

int main()
{
auto future = std::async(func_1, 2);

//More code later

int number = future.get(); //Whole program waits for this

// Do something with number

return 0;
}

In short, .get() gets the return value, you can typecast and use it then.



Related Topics



Leave a reply



Submit