Is it possible to display a message or make changes on the UI thread once Task callInBackground is finished executing?
Something like following:
Task.callInBackground(new Callable<String>() {
#Override
public String call() {
for(int i=0; i<3; i++){
Log.i("I=", String.valueOf(i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String obj = "";
return null;
}
}).onSuccess(new Continuation<String, Object>() {
#Override
public Object then(Task<String> task) throws Exception {
Log.i("I=", "Counter complete");
Toast.makeText(MainLoanMemberActivity.this, "Finished", Toast.LENGTH_SHORT).show();
btnAgriLoan.setText("LOL");
return null;
}
});
At the moment there is no Toast message displayed and there is no crash as well.
Looking for an equivalent of AsyncTask's onPostExecute in Bolts Framework where one can add changes to UI.
Didn't realized that there are EXECUTOR's types that you can mentioned with each helper function like so: (Task.UI_THREAD_EXECUTOR)
Task.callInBackground(new Callable<String>() {
#Override
public String call() {
for(int i=0; i<3; i++){
Log.i("I=", String.valueOf(i));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String obj = "";
return null;
}
}).onSuccess(new Continuation<String, Void>() {
public Void then(Task<String> object) throws Exception {
Toast.makeText(MainLoanMemberActivity.this, "Finished", Toast.LENGTH_SHORT).show();
btnAgriLoan.setText("LOL");
return null;
}
}, Task.UI_THREAD_EXECUTOR);
Docs helped!
I am working on Android Chat app based on Smack 4.1.7.
I have created my XMPP related operations on Saperate class said MyXMPP.java.
and in my app's Application class i am initializing MyXMPP class objects.
my problem is, suppose we have user 1 and user 2. if user 1 sends message to user 2 then user 2 can get message but cant reply back. means if user 2 trying to reply then user 1 can not get user 2's reply.
in short if user 1 initiates chatting then, only user 1 can send message. user 2 can not send message to user 1 same Vice versa.
my codes are as below,
MyXMPP.java
public class MyXMPP {
static Context context;
static XMPPTCPConnectionConfiguration.Builder xmppConfig;
static XMPPTCPConnection connection;
static MyXMPP myXMPP = null;
static Chat chat;
Roster roster;
ArrayList<Rosters> rosters;
static ChatManager chatManager;
static Application app;
public static synchronized MyXMPP getInstance(Context c) {
app = (Application) c.getApplicationContext();
context = c;
if (myXMPP == null) {
myXMPP = new MyXMPP();
xmppConfig = XMPPTCPConnectionConfiguration.builder();
xmppConfig.setResource(Constants.RESOURCE);
xmppConfig.setServiceName(Constants.SERVICE_NAME);
xmppConfig.setPort(Constants.PORT);
xmppConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
}
return myXMPP;
}
public static synchronized AbstractXMPPConnection getConnectXMPP() {
try {
xmppConfig.setUsernameAndPassword(Constants.USERNAME, Constants.PASSWORD);
XMPPTCPConnection.setUseStreamManagementDefault(true);
connection = new XMPPTCPConnection(xmppConfig.build());
connection.setUseStreamManagement(true);
connection.connect().login();
connection.requestSmAcknowledgement();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
}
return connection;
}
public static ChatManager getChatManager() {
if (chatManager == null) {
chatManager = ChatManager.getInstanceFor(app.connection);
}
return chatManager;
}
public ArrayList<Rosters> getRosters() {
rosters = new ArrayList<>();
roster = Roster.getInstanceFor(app.connection);
if (!roster.isLoaded())
try {
roster.reloadAndWait();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (SmackException.NotLoggedInException e) {
e.printStackTrace();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
//Get Roster Entry list
Set<RosterEntry> rosterEntries = roster.getEntries();
Debug.e("entry size", "" + rosterEntries.size());
for (final RosterEntry entry : rosterEntries) {
/*
build List<> for roster entry with roster
---or---
if it is in activity or in fragment then add both items (entry,roster) to adapter
*/
Rosters rosterItem = new Rosters();
rosterItem.entry.add(entry);
rosterItem.roster.add(roster);
rosters.add(rosterItem);
}
return rosters;
}
public void initChatManager() {
if (chatManager == null) {
chatManager = getChatManager();
}
chatManager.addChatListener(new ChatManagerListener() {
#Override
public void chatCreated(Chat chat, boolean createdLocally) {
MyXMPP.chat = chat;
if (!createdLocally) {
chat.addMessageListener(new ChatMessageListener() {
#Override
public void processMessage(Chat chat, Message message) {
Debug.e("Chat obj", chat.toString());
if (message != null || !message.getBody().equalsIgnoreCase(null) || !message.getBody().equalsIgnoreCase("")) {
if (message.getBody() == null || message.getBody().equals(null)) {
} else {
Debug.e("Message aala", "" + message.getBody());
}
} else {
Debug.e("message null", "Message Null");
}
}
});
} else {
Debug.e("MY MSG", chat.getParticipant());
}
}
});
}
public void sendMessage(String to, String msg) {
Chat newChat = app.myXMPP.getChatManager().createChat(to, new ChatMessageListener() {
#Override
public void processMessage(Chat chat, Message message) {
System.out.println("Received message: " + message);
}
});
try {
Message message = new Message();
message.setFrom(connection.getUser());
message.setTo("xyz#myhostaddress.com");
message.setBody("My Message");
newChat.addMessageListener(new ChatMessageListener() {
#Override
public void processMessage(Chat chat, Message message) {
Debug.e("send msg listener", message.getBody());
}
});
newChat.sendMessage(message);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
Application app;
Button btn;
String threadId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
app.myXMPP.sendMessage("xyz#myhost.com", "hello");
}
});
//Get Application data access
app = (Application) getApplicationContext();
//Establish Connection and Login
new XMPPOperations().execute();
}
class XMPPOperations extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
if (app.connection == null || !app.connection.isConnected()) {
app.connection = app.myXMPP.getConnectXMPP();
Debug.e("Connection in activity", "" + app.connection.isConnected());
}
app.myXMPP.getRosters();
app.myXMPP.initChatManager();
return null;
}
}
}
Application.java
public class Application extends android.app.Application {
public MyXMPP myXMPP;
public AbstractXMPPConnection connection;
#Override
public void onCreate() {
super.onCreate();
myXMPP = MyXMPP.getInstance(this);
}
#Override
public void onTerminate() {
super.onTerminate();
Presence p = new Presence(Presence.Type.unavailable);
try {
connection.sendStanza(p);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
}
}
I have a problem in change a text of a textview in android, i'm starting in android, ok I want do a chat with sockets, I made the socket and connected on server but i can't change the text of the textview, ok this is the code:
public class Cliente extends Activity {
Button conect;
Button env;
EditText ip;
EditText nome;
EditText msg;
String nome_txt;
String ip_txt;
Socket cl;
String texto = "";
TextView log;
boolean a = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_layout);
conect = (Button) findViewById(R.id.conect);
env = (Button) findViewById(R.id.env);
msg = (EditText) findViewById(R.id.msg);
ip = (EditText) findViewById(R.id.ip_tx);
nome = (EditText) findViewById(R.id.nm_tx);
log = (TextView) findViewById(R.id.log);
conect.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
ip_txt = ip.getText().toString();
nome_txt = nome.getText().toString();
setContentView(R.layout.activity_cliente);
Thread th =new Thread(new Ct());
Log.d("Iniciado", "th");
log.setText("asd");
th.start();
}
});
env.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
try {
envMSG(msg.getText().toString());
msg.setText("");
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public void envMSG(String msg) throws IOException {
DataOutputStream outToServer = new DataOutputStream(cl.getOutputStream());
outToServer.writeBytes(msg + '\n');
}
public String serOUT() {
try{
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(cl.getInputStream()));
if (inFromServer.ready()) {
String texto = inFromServer.readLine();
return texto;
} else {
return null;
}
}catch(IOException e){
return null;
}
}
public class Ct extends Thread implements Runnable{
#Override
public void run() {
try {
cl = new Socket(ip_txt, 1111);
envMSG(nome_txt);
do{
String tx = serOUT();
if (tx != null) {
texto += tx + "\n";
log.setText(texto);
envMSG("ola");
}
Log.d("Status",cl.isClosed()+"");
this.sleep(10);
}while (true);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Please tell the error reason, and show examples.
Thanks for Reading.
ass.:Lucas Avelino
First of all, you cant set text inside thread, you have to ovveride runOnUiThread method and try to set text in this method.
public class Ct extends Thread implements Runnable{
#Override
public void run() {
try {
cl = new Socket(ip_txt, 1111);
envMSG(nome_txt);
do{
String tx = serOUT();
if (tx != null) {
runOnUiThread(new Runnable() {
#Override
public void run() {
texto += tx + "\n";
log.setText(texto);
envMSG("ola");
}
});
}
Log.d("Status",cl.isClosed()+"");
this.sleep(10);
}while (true);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I throw a exception with some message like:
public static ILSResponseEmailLookUPBO getILSUserAccounts(Resources res,
String email) throws TripLoggerCustomException,
TripLoggerUnexpectedErrorException {
String resp = null;
String lookupURL;
try {
lookupURL = TripLoggerConstants.ServerConstants.ILS_LOOKUP_URL
+ URLEncoder.encode(email, "UTF-8");
} catch (UnsupportedEncodingException e1) {
throw new TripLoggerCustomException(
res.getString(R.string.error_try_again));
}
try {
resp = ConnectionManager.getInstance().httpRequest(lookupURL,
TripLoggerConstants.RequestMethods.GET);
} catch (IOException e) {
if (e.getMessage().equals(
res.getString(R.string.network_unreachable))
|| e.getMessage().equals(
res.getString(R.string.host_unresolved))) {
throw new TripLoggerCustomException(
res.getString(R.string.network_not_reachable));
} else {
throw new TripLoggerCustomException(
res.getString(R.string.email_notfound_ils));
}
}
here my else part execute.
And my exception class is:
public class TripLoggerCustomException extends Exception {
private String customMessage;
private static final long serialVersionUID = 1L;
public TripLoggerCustomException() {
super();
}
public TripLoggerCustomException(String message) {
super(message);
this.customMessage = (message == null ? "" : message);
}
public String getCustomMessage() {
return this.customMessage;
}
public void setCustomMessage(String customMessage) {
this.customMessage = customMessage;
}
}
And here i catch this exception:
private void manageLookUpActions(final String emailID) {
new Thread() {
public void run() {
try {
listILSAccounts = ILSLookupEmailBL.getILSUserAccounts(
getResources(), emailID);
} catch (TripLoggerCustomException e) {
dismissProgressBar();
handleException(e.getMessage());
return;
} catch (TripLoggerUnexpectedErrorException e) {
dismissProgressBar();
handleException(e.getMessage());
return;
}
}
}.start();
}
but here in catch of TripLoggerCustomException e is null.why?Can anyone help me?
After looking into multiple reports on StackOverflow, it seems like this is not an actual issue. Multiple people have been saying that it is a problem in the combination of the Eclipse debugger and the Android Emulator. That is why you don't get a NullPointerException, which you would definitely get if e was null.
So this is probably not an issue you have to worry about.
This might be a complex problem with my application but I'll do my best to describe it as accurately as I can.
I am making an Android Client and making use of a couple of helper classes someone else handed to me at work. The helper Android classes are called TcpClient.java and PVDCAndroidClient.java. PVDCAndroidClient.java makes use out of the TcpCLient, using a tcpCLient object to connect via serverIP and port.
Here is PVDCAndroidClient.java:
public class PVDCAndroidClient {
// constants
public static final String DEFAULT_LOGIN_URI = "http://me.net:8000/";
private TcpClient tcpClient = null;
private UdpClient udpClient = null;
private boolean connected = false;
private boolean loggedin = false;
private static SimpleDateFormat sdf;
private String loginURI = DEFAULT_LOGIN_URI;
private int getUserNumber;
TcpMessageListener listener = null;
/**
* Connects to proxy server, blocks until complete or timeout
* #param serverIP
* #param port
*/
public void connect(String serverIP, int port)
{
try
{
if(serverIP.length() != 0 && port != 0)
{
tcpClient = new TcpClient();
tcpClient.addTcpListener(listener);
tcpClient.connect(serverIP, port);
}
}
catch(Exception e)
{
e.printStackTrace();
Log.d("Could not connect to server, possbile timeout...", "error");
}
}
///// Make login function a blocking call
// Default login, use last location as login location
public boolean login(String fName, String lName, String password)
{
return this.login(fName, lName, password, "last location");
}
public boolean login(String fName, String lName, String password, String region)
{
return this.login(fName, lName, password, "last location", 128, 128, 20);
}
public boolean login(String fName, String lName, String password, String region, int loginX, int loginY, int loginZ)
{ sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
// Check passed values
// x, y and z should be between [0, 256]
// strings should not be null or empty(except lName which can be empty)
if((loginX >= 0 && loginX <= 256) && (loginY >=0 && loginY <= 256) && (loginZ >= 0 && loginZ <= 256))
{
if(fName.length() != 0 && fName != null)
{
// Construct packet xml structure
// Send request and wait until reply or timeout
// return false if timeout (or throw exception?)
// if not timeout, read result packet and determine return value
// getUserNumber = tcpClient.getUserNum();
StringWriter stringWriter = new StringWriter();
XmlSerializer serializer = Xml.newSerializer();
try {
serializer.setOutput(stringWriter);
// Indentation is not required, but helps with reading
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
// TODO: Remove hardcoding of strings, make either constants or place in strings.xml
// TODO: Move the header construction to other method as it is fairly constant other than request num and no need to repeat that much code
serializer.startTag("", "pvdc_pkt");
serializer.startTag("", "pvdc_header");
// TODO: replace this with a string unique to the system
serializer.startTag("", "ID");
serializer.text("838393djdjdjd");
serializer.endTag("", "ID");
// TODO: replace this with actual user number from server
serializer.startTag("", "user_num");
serializer.text("22");//get userNum from above
serializer.endTag("", "user_num");
// TODO: add a request number counter to increment this on each request
serializer.startTag("", "request_num");
serializer.text("1");
serializer.endTag("", "request_num");
serializer.startTag("", "DateTime");
serializer.text(sdf.toString()); //utc time variable.
serializer.endTag("", "DateTime");
serializer.endTag("", "pvdc_header");
serializer.startTag("", "pvdc_content");
serializer.attribute("", "type", "requestlogin");
serializer.startTag("", "name");
serializer.attribute("", "fname", fName);
serializer.attribute("", "lname", lName);
serializer.endTag("", "name");
serializer.startTag("", "password");
serializer.text(password);
serializer.endTag("", "password");
serializer.startTag("", "server");
serializer.text(this.loginURI);
serializer.endTag("", "server");
serializer.startTag("", "location");
serializer.attribute("", "region", region);
serializer.text(loginX + ";" + loginY +";" + loginZ);
serializer.endTag("", "location");
serializer.endTag("", "pvdc_content");
serializer.endTag("", "pvdc_pkt");
// Finish writing
serializer.endDocument();
// write xml data out
serializer.flush();
//
sendLogin(stringWriter);
} catch (Exception e) {
Log.e("Exception", "error occurred while creating xml file");
return false;
}
// Print out xml for debugging
Log.d("PVDCAndroidClient Login", stringWriter.toString().trim());
}
else
{
Log.d("Error in name checking", "fName either blank or null");
}
}
else
{
Log.d("login coordinates X,Y, or Z not between 0-256", "Coordinates Error");
}
return true;
}
// moveString should contain the properly formatted movement command(s)[see above move request description]
public void sendLogin(StringWriter stringWriter)
{
tcpClient.sendMessage(stringWriter.toString());
}
}
Here is the actual TcpClient.java:
public class TcpClient {
public interface TcpMessageListener{
public void onMessage(TcpClient client, String message);
}
private Socket socket = null;
private PrintWriter out = null;
private BufferedReader in = null;
private Thread listenThread = null;
private boolean listening = false;
private int userNum = -1;
private List<TcpMessageListener> listeners = new ArrayList<TcpMessageListener>();
public int getUserNum()
{
return this.userNum;
}
public TcpClient() {
}
public void addTcpListener(TcpMessageListener listener)
{
synchronized(this.listeners)
{
this.listeners.add(listener);
}
}
public void removeTcpListener(TcpMessageListener listener)
{
synchronized(this.listeners)
{
this.listeners.remove(listener);
}
}
public boolean connect(String serverIpOrHost, int port) {
try {
socket = new Socket(serverIpOrHost, port);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.listenThread = new Thread(new Runnable(){
public void run() {
int charsRead = 0;
char[] buff = new char[4096];
while(listening && charsRead >= 0)
{
try {
charsRead = in.read(buff);
if(charsRead > 0)
{
Log.d("TCPClient",new String(buff).trim());
String input = new String(buff).trim();
synchronized(listeners)
{
for(TcpMessageListener l : listeners){
l.onMessage(TcpClient.this, input);
}
}
if (input.toLowerCase().contains("<user_num>")){
int index = input.toLowerCase().indexOf("<user_num>");
index += "<user_num>".length();
int index2 = input.toLowerCase().indexOf("</user_num>");
userNum = Integer.parseInt(input.substring(index, index2));
}
}
} catch (IOException e) {
Log.e("TCPClient", "IOException while reading input stream");
listening = false;
}
}
}
});
this.listening = true;
this.listenThread.setDaemon(true);
this.listenThread.start();
} catch (UnknownHostException e) {
System.err.println("Don't know about host");
return false;
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection");
return false;
} catch (Exception e) {
System.err.println(e.getMessage().toString());
return false;
}
return true;
}
public void sendMessage(String msg) {
if(out != null)
{
out.println(msg);
out.flush();
}
}
public void disconnect() {
try {
if(out != null){
out.close();
out = null;
}
if(in != null){
in.close();
in = null;
}
if (socket != null) {
socket.close();
socket = null;
}
if(this.listenThread != null){
this.listening = false;
this.listenThread.interrupt();
}
this.userNum = -1;
} catch (IOException ioe) {
System.err.println("I/O error in closing connection.");
}
}
}
LASTLY, here is what I have been coding today and cannot seem to get this to work. I don't get any blatant exceptions, just a warning on Logcat, that says, "Couldn't get I/O for the connection".
public class AndroidClientCompnt extends Activity {
private TcpClient myTcpClient = null;
private UdpClient udpClient;
private static final String IP_ADDRESS_SHARED_PREFS = "ipAddressPref";
private static final String PORT_SHARED_PREFS = "portNumberPref";
private String encryptPassLoginActivity;
private String getIpAddressSharedPrefs;
private String getPassword, getName, getRegionSelect, getGridSelect;
private String fName, lName;
private SharedPreferences settings;
private boolean resultCheck = false;
private int portNum;
PVDCAndroidClient client;
private String name;
private CharSequence[] getView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
Intent intent = getIntent();
// getting object's properties from LoginActivity class.
getName = intent.getStringExtra("name");
getPassword = intent.getStringExtra("password");
getRegionSelect = intent.getStringExtra("regionSelect");
getGridSelect = intent.getStringExtra("gridSelect");
Log.d("VARIABLES", "getName = " + getName + "getPassword" + getPassword
+ "getRegionSelect = " + getRegionSelect + ".");
setResult(Activity.RESULT_CANCELED);
client = new PVDCAndroidClient();
}
#Override
protected void onStart() {
super.onStart();
// Take care of getting user's login information:
// grid selected as well? sometime?
settings = PreferenceManager.getDefaultSharedPreferences(this);
getIpAddressSharedPrefs = settings.getString(IP_ADDRESS_SHARED_PREFS,
"");
portNum = Integer.parseInt(settings.getString(PORT_SHARED_PREFS, ""));
Log.d("SHARED" + getIpAddressSharedPrefs + "port " + portNum, "");
if (getIpAddressSharedPrefs.length() != 0 && portNum != 0) {
try {
// first connect attempt.
client.connect(getIpAddressSharedPrefs, portNum);
resultCheck = client.isConnected();
// here is where I want to call Async to do login
// or do whatever else.
UploadTask task = new UploadTask();
task.execute();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "Could not connect.",
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(),
"Ip preference and port blank", Toast.LENGTH_LONG).show();
}
finish();
}
private class UploadTask extends AsyncTask<String, Integer, Void> {
#Override
protected void onPreExecute() {
Toast.makeText(getApplicationContext(), "Loading...",
Toast.LENGTH_LONG).show();
}
#Override
protected Void doInBackground(String... names) {
// encrypting user's password with Md5Hash class.
try {
encryptPassLoginActivity = MdHashing
.MD5(getPassword.toString());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (resultCheck == true) {
String[] firstAndLast;
String spcDelmt = " ";
firstAndLast = name.toString().split(spcDelmt);
fName = firstAndLast[0];
lName = firstAndLast[1];
// set up the tcp client to sent the information to the
// server.
client.login(fName, lName, encryptPassLoginActivity,
getRegionSelect, 128, 128, 20);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
Intent goToInWorld = new Intent(
AndroidClientCompnt.this.getApplicationContext(),
PocketVDCActivity.class);
startActivity(goToInWorld);
Toast.makeText(getApplicationContext(), "Connected",
Toast.LENGTH_LONG).show();
}
}
}
I know this is a super long post and I am asking a lot but if anyone could take a look at this I would very much appreciate it. I've been at this all day, trying to make use of these helper classes I got and can't get it to work. It also doesn't help that I'm not too experienced in this client/server stuff. Any nudges in the right direction or an accepted solution would REALLY mean something to me.
Thank you kindly,
Have a good evening.
Can you post your manifest?
You may need to add the following :
<uses-permission android:name="android.permission.INTERNET"/>
Additionally - I assume you see nothing ever happen on the server side of this connection?
1) Make sure you have the following permission in your Android-Manifest file:
<uses-permission android:name="android.permission.INTERNET/>
w/o this you definitely won't be making any tcp/ip connections.
2) You will want to run the code in debug mode, and place breakpoints where the connection information
is set and also what results are at several points. In other words you need to dig deeper.
If you are somewhat new to coding there is no better investment of time than in running the debugger and stepping line by line through the code. Code only comes to life inside a debugger, where you can see the values of variables and results. So set several breakpoints, step through and you will see more. It is more difficult to debug where there are threads however.