I am using "programming in D" to learn about D language. I wrote a simple program that spawns a worker and sends it a number to receive its square as a string. The worker 1 gets the number squares it and sends to worker 2 (a different function) to get casted as string which is returned to the worker 1 and thus it returns it to the main function call. I can write the whole thing in a single thread. I wrote it to understand about workers better. I used receive to get the worker 1 act as per the input. The program is as follows
import std.stdio;
import std.concurrency;
import std.conv;
import core.thread;
void main() {
foreach (int num; 1..100) {
auto square_tid = spawn(&square);
square_tid.send(num);
auto square = receiveOnly!string();
writeln(square);
}
}
void square() {
static i = 0;
receive (
(int num) {
auto square = num * num;
writeln("sqaure : Comes in with " , num , " for " , ++i , " time");
auto stringWorker = spawn(&stringConverter);
stringWorker.send(thisTid, square, ownerTid);
},
(Tid tid, string str) {
writeln("comes in string");
send(tid, "hello");
});
}
void stringConverter() {
static i = 0;
auto params = receiveOnly!(Tid, int, Tid)();
auto stringified = to!string(params[1]); // Stringify the square
writeln("string : Comes in with " , params[1], " for " , ++i , " time");
params[0].send(params[2], stringified); // params[0] - square function tid, params[2] - main function tid
}
I can receive the main function tid and directly send the string back. But when I return to the worker 1 it gets struck and doesn't proceed further. How can I make a thread to receive input from master thread and also from the slave thread. Another few questions about threads :
If I want to send -1 as the data to my worker without exiting it. How can I do it?
Is it ok to use a single worker for the whole process or I can use multiple workers as I did in the foreach loop?
The book uses the following code. Why does it have the value >= 0 as its obvious in the code.
import std.stdio;
import std.concurrency;
import std.conv;
void main() {
Tid worker = spawn(&workerFunc);
foreach (value; 1 .. 5) {
worker.send(value);
double result = receiveOnly!double();
writefln("sent: %s, received: %s", value, result);
}
/* Sending a negative value to the worker so that it
* terminates. */
worker.send(-1);
}
void workerFunc() {
int value = 0;
while (value >= 0) {
value = receiveOnly!int();
double result = to!double(value) / 5;
ownerTid.send(result);
}
}
Correct me if I am wrong in any of the terminologies.
For this kind of task is better to use std.parallelism
import std.stdio;
import std.parallelism;
void main() {
auto squares = new long[100];
foreach(i, ref elem; parallel(squares)) {
elem = i * i;
}
writeln(squares);
}
And there is no problem with sending -1 to worker thread, it will not exit thread only when it is explicitly ask.
And here is a modified version of your attempt:
import std.stdio;
import std.concurrency;
import std.conv;
void main() {
foreach (int num; 1..100) {
auto square_tid = spawn(&square);
square_tid.send(num);
auto square = receiveOnly!string();
writeln(square);
}
}
void square() {
static shared i = 0;
receive (
(int num) {
int square = num * num;
writeln("sqaure : Comes in with " , num , " for " , ++i , " time");
auto stringWorker = spawn(&stringConverter);
stringWorker.send(thisTid, square, ownerTid);
receive ((Tid tid, string str) { writeln("comes in string"); send(tid, "hello");});
});
}
void stringConverter() {
static shared i = 0;
auto params = receiveOnly!(Tid, int, Tid)();
auto stringified = to!string(params[1]); // Stringify the square
writeln("string : Comes in with " , params[1], " for " , ++i , " time");
params[0].send(params[2], stringified); // params[0] - square function tid, params[2] - main function tid
}
UPDATE explanation
the square function in your code ends after receive. So it never try the next block with (Tid tid, string str) part. This is why I put it inside the first part of receive.
With each call of spawn you creating new thread. And because D use TLS by default the static keyword is useless in your example. Because in every new thread i would be 0. This is why I use shared keyword.
UPDATE 2
here is a version which could explain more how things works:
import std.stdio;
import std.concurrency;
import std.conv;
void main() {
foreach (int num; 1..100) {
auto square_tid = spawn(&square);
square_tid.send(num);
auto square = receiveOnly!string();
writeln(square);
}
}
void square() {
shared static i = 0;
bool end = false;
while(!end) receive (
(int num) {
auto square = num * num;
writeln("sqaure : Comes in with " , num , " for " , ++i , " time");
auto stringWorker = spawn(&stringConverter);
stringWorker.send(square);
},
(string str) {
writeln("comes in string");
ownerTid.send(str);
end = true;
});
}
void stringConverter() {
shared static i = 0;
auto params = receiveOnly!(int)();
auto stringified = to!string(params); // Stringify the square
writeln("string : Comes in with " , params, " for " , ++i , " time");
ownerTid.send(stringified); // params[0] - square function tid, params[2] - main function tid
}
Related
I'm making a clock and I want a specific input to be able to stop it.
Any ideas?
Here's my code:
public static void main(String[] args) {
//...
Scanner input = new Scanner(System.in);
//...
int s = 0;
int m = 0;
int h = 0;
clock: // label to break a outer most loop
for(int i = 0; i<2; i++) {
on = Boolean.parseBoolean(onValue[i]);
while (on = true) {
for (i=1; i<=60; i++) {
s++;
if(input2check.compareTo("") == 0) {
on = Boolean.parseBoolean(onValue[1]);
break clock;
}
if (s == 60) {
s = 0;
}
System.out.println(s + " sec" );
}
}
}
}
First idea: do the Scanner in a separate thread
As you've noticed, Scanner.nextLine blocks until the user has input something and pressed Enter. We can ignore this problem if our clock does not run in the same thread as the Scanner loop. Let's use a daemon thread for reading user input.
I've picked the word "off" as stopping input from the user.
import java.util.Scanner;
public class Clock1 {
private static volatile boolean on = true;
public static void main(String[] args) throws InterruptedException {
int s = 0, m = 0, h = 0;
Thread t = new Thread(() -> {
try (Scanner scan = new Scanner(System.in)) {
while (on) {
String input = scan.nextLine();
if (input == null)
continue;
if ("off".equalsIgnoreCase(input.trim())) {
on = false;
}
}
}
});
t.setName("console");
t.setDaemon(true);
t.start();
clock: for (int i = 0; i < 2; i++) { //Why this loop ?
long prevTime = System.nanoTime();
long diff;
while (on) {
if (++s % 60 == 0) {
s = 0;
if (++m % 60 == 0) {
m = 0;
++h;
}
}
do {
diff = System.nanoTime() - prevTime;
Thread.sleep(Math.min(1000 - diff / 1_000_000L, 100));
} while (on && diff < 1_000_000_000L);
if (!on)
break clock;
prevTime = System.nanoTime();
System.out.println(String.format("%02d:%02d:%02d", h, m, s));
}
}
System.out.println("Clock stopped");
}
}
You need to be aware that timing a clock with Thread.sleep is inaccurate, though. But it may be enough for your problem...
I tried to compensate for this using several checks for System.nanoTime per second, but accurate timing would require a more complex algorithm. It also allows for about immediate reaction to user input.
Second idea: use a BufferedReader rather than a Scanner
Using a BufferedReader allows us to avoid blocking execution while we check if the buffer is ready, and then only read user input when they've pressed Enter, thus bypassing the problem with Scanner.nextLine.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class Clock2 {
private static volatile boolean on = true;
public static void main(String[] args) throws InterruptedException, IOException {
int s = 0, m = 0, h = 0;
try (BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8))) {
clock: for (int i = 0; i < 2; i++) { // Why this loop ?
long prevTime = System.nanoTime();
long diff;
while (on) {
if (++s % 60 == 0) {
s = 0;
if (++m % 60 == 0) {
m = 0;
++h;
}
}
do {
diff = System.nanoTime() - prevTime;
Thread.sleep(Math.min(1000 - diff / 1_000_000L, 100));
String line;
while (on && rdr.ready() && (line = rdr.readLine()) != null) {
if (line.trim().equalsIgnoreCase("off"))
on = false;
}
} while (on && diff < 1_000_000_000L);
if (!on)
break clock;
prevTime = System.nanoTime();
System.out.println(String.format("%02d:%02d:%02d", h, m, s));
}
}
}
System.out.println("Clock stopped");
}
}
Third idea: use a ScheduledExecutor
This time, the clock is timed by a ScheduledExecutor that executes the increment loop once per second in a separate thread as the main program.
Accumulated values had to be stored in a class, so I also implemented AutoCloseable with class Clock3 to ease shutting down the executor when the clock stops.
User input is read in a loop in the main thread using a Scanner until we hit the word "off".
import java.util.Scanner;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Clock3 implements AutoCloseable {
private static volatile boolean on = true;
private ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
private int s = 0, m = 0, h = 0;
public static void main(String[] args) throws Exception {
try (Clock3 clock = new Clock3()) {
try (Scanner scan = new Scanner(System.in)) {
while (on) {
String input = scan.nextLine();
if (input == null)
continue;
if ("off".equalsIgnoreCase(input.trim())) {
on = false;
}
}
}
}
System.out.println("Clock stopped");
}
public Clock3() {
exec.scheduleAtFixedRate(() -> {
if (++s % 60 == 0) {
s = 0;
if (++m % 60 == 0) {
m = 0;
++h;
}
}
if (on)
System.out.println(String.format("%02d:%02d:%02d", h, m, s));
}, 0, 1, TimeUnit.SECONDS);
}
#Override
public void close() throws Exception {
exec.shutdownNow();
}
}
I don't know how accurate this scheduling is guaranteed to be. From what I can read from documentation for ScheduledExecutorService.scheduleAtFixedRate:
If any execution of this task takes longer than its period, then subsequent executions may start late.
Which will never be the case with this small increment algorithm.
There are probably better ways of scheduling that however, but that was not the point of your question...
I have QList which contains inhereted from QThread objects. These objects in run() method do some work in cycle with different periodicity(I use QThread::sleep) and results save in private fields.
Question
How correct print result in QTableView or QTableWidget?
my idea - create thread that will print in QTableWidget result in infinity cycle, but I guess that this idea is terrible...
//httpgettask.h
//Task inherit from QThread
class HttpGetTask : public Task
{
public:
HttpGetTask(const QString &, const int &, const int &);
HttpGetTask(const QUrl &, const int &, const int &);
void run();
};
//httpgettask.cpp
HttpGetTask::HttpGetTask(const QUrl &url, const int &period, const int &errLimit) :
Task(url, period, errLimit, "HTTP GET")
{
}
HttpGetTask::HttpGetTask(const QString &url, const int &period, const int &errLimit) :
Task(url, period, errLimit, "HTTP GET")
{
}
void HttpGetTask::run()
{
TestConn conn(url);
Response res;
QString msg;
int errCount = 0;
while (!stopThread)
{
msg = "";
res = conn.get();
if (!res.isSuccess())
{
if (++errCount == errLimit) {
msg = QString("ERROR!! %1 ERROR").arg(errLimit);
++errors;
errCount = 0;
}
}
msg = QString("%1 %2 %3 %4").arg(QDateTime::currentDateTime().toString(datePattern),
msg,
"HTTP_GET",
res.getMessage());
writeResultFile(msg);
++checkCount;
QThread::sleep(period);
}
}
I solved the problem. Just create QTimer and update QTableWidget in timer slot
I have an application within Unity3D (acting as a server) that receives messages from an exterior application (single client) with the following structure:
number(float) number(float) number(float)
The first two numbers represent the local position (x,z axis) and the last one a rotation value (y axis).
The goal is to use this data to update the Camera gameobject position (using the LoadPositions method) within the game scene. From what I've read manipulating gameobjects while outside Unity's main thread is not possible.
With that being said how can I change from and to Unity main thread so that I can both listen for messages and update the gameobjects position.
Also, anyone happens to know of a working example of a simple TCP Server in Unity without having to resort to threads?
using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System;
using System.Text;
using System.Collections.Generic;
public class ProxyThreadServer : MonoBehaviour {
float x;
float z;
float rot;
Vector3 updatePos;
Vector3 updateRot;
string ip_address = "127.0.0.1";
string msgReceived;
string[] words;
int wordsNum;
int port = 8000;
int numSurf;
int jumpInterval;
Thread listen_thread;
TcpListener tcp_listener;
Thread clientThread;
TcpClient tcp_client;
bool isTrue = true;
// Use this for initialization
void Start ()
{
IPAddress ip_addy = IPAddress.Parse(ip_address);
tcp_listener = new TcpListener(ip_addy, port);
listen_thread = new Thread(new ThreadStart(ListenForClients));
listen_thread.Start();
}
private void ListenForClients()
{
this.tcp_listener.Start();
while(isTrue == true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcp_listener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
Debug.Log("Got client " + client);
}
}
private void HandleClientComm(object client)
{
tcp_client = (TcpClient)client;
NetworkStream client_stream = tcp_client.GetStream();
byte[] message = new byte[4096];
int bytes_read;
while(isTrue == true)
{
bytes_read = 0;
try
{
//blocks until a client sends a message
bytes_read = client_stream.Read(message, 0, 4096);
//Debug.Log(message);
}
catch (Exception e)
{
//a socket error has occurred
Debug.Log(e.Message);
break;
}
if(bytes_read == 0)
{
//client has disconnected
Debug.Log("Disconnected");
tcp_client.Close();
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
Debug.Log(encoder.GetString(message,0,bytes_read));
msgReceived = encoder.GetString(message,0,bytes_read);
LoadPositions(msgReceived);
}
if(isTrue == false)
{
tcp_client.Close();
Debug.Log("closing tcp client");
}
}
void OnApplicationQuit()
{
try
{
tcp_client.Close();
isTrue = false;
}
catch(Exception e)
{
Debug.Log(e.Message);
}
// You must close the tcp listener
try
{
tcp_listener.Stop();
isTrue = false;
}
catch(Exception e)
{
Debug.Log(e.Message);
}
}
void LoadPositions(string positions){
// Split string on spaces. This will separate all the words.
words = positions.Split(' ');
wordsNum = words.Length;
for (int i = 0; i <= wordsNum; i++) {
x = float.Parse(words[0], System.Globalization.CultureInfo.InvariantCulture);
z = float.Parse(words[1], System.Globalization.CultureInfo.InvariantCulture);
rot = float.Parse(words[2], System.Globalization.CultureInfo.InvariantCulture);
Debug.Log("Reading position: " + "x: " + x + " z: " + z + " yRot: " + rot);
updatePos = new Vector3(x, this.gameObject.transform.position.y, z);
this.gameObject.transform.position = updatePos;
updateRot = new Vector3(this.gameObject.transform.rotation.x, rot / 4, this.gameObject.transform.rotation.z);
this.transform.localEulerAngles = updateRot;
//UpdateCameraMatrix();
//StartCoroutine(UpdateSurfs());
}
}
}
While I haven't tried to do something quite like this before, assuming the limitations do exist as you mentioned, my approach would be to use a queue to store the messages then process them in the order they came in on the unity thread. So instead of calling LoadPositions when it comes it, add it to a queue
pendingMessages.Enqueue(msgReceived);
Then in the update method you process it:
void Update()
{
while (pendingMessages.Count() > 0)
LoadPositions(pendingMessages.Dequeue());
}
You can use .NET's Async TCP. It's based on callback delegates. (Working with it is a bit tricky though)
I am writing a program that does simple math problems. What I am trying to do is to make it so that even if I input a string into the the scanner level it will not give me an error. The level is to choose the difficulty of the math problems. I have tried parseInt, but am at a loss of what to do now.
import java.util.Random;
import java.util.Scanner;
public class Test {
static Scanner keyboard = new Scanner(System.in);
static Random generator = new Random();
public static void main(String[] args) {
String level = intro();//This method intorduces the program,
questions(level);//This does the actual computation.
}
public static String intro() {
System.out.println("HI - I am your friendly arithmetic tutor.");
System.out.print("What is your name? ");
String name = keyboard.nextLine();
System.out.print("What level do you choose? ");
String level = keyboard.nextLine();
System.out.println("OK " + name + ", here are ten exercises for you at the level " + level + ".");
System.out.println("Good luck.");
return level;
}
public static void questions(String level) {
int value = 0, random1 = 0, random2 = 0;
int r = 0, score = 0;
int x = Integer.parseInt("level");
if (x==1) {
r = 4;
}
else if(x==2) {
r = 9;
}
else if(x==3) {
r = 50;
}
for (int i = 0; i<10; i++) {
random1 = generator.nextInt(r);//first random number.
random2 = generator.nextInt(r);//second random number.
System.out.print(random1 + " + " + random2 + " = ");
int ans = keyboard.nextInt();
if((random1 + random2)== ans) {
System.out.println("Your answer is correct!");
score+=1;
}
else if ((random1 + random2)!= ans) {
System.out.println("Your answer is wrong!");
}
}
if (score==10 || score==9) {
if (score==10 && x == 3) {
System.out.println("This system is of no further use.");
}
else {
System.out.println("Choose a higher difficulty");
}
System.out.println("You got " + score + " out or 10");
}
else if (score<=8 && score>=6) {
System.out.println("You got " + score + " out or 10");
System.out.println("Do the test again");
}
else if (score>6) {
System.out.println("You got " + score + " out or 10");
System.out.println("Come back for extra lessons");
}
}
}
The first error I see is that you tried to Integer.parseInt() a String "level" instead of the String variable named level
int x = Integer.parseInt("level");
should be
int x = Integer.parseInt(level);
Also, when defining level you can use keyboard.nextInt instead of keyboard.nextLine
String level = keyboard.nextInt();
Then, you wouldn't have to do an Integer.parseInt() operation later on
This following code gives me the error below . I think I need "InvokeRequired" . But I don't understand how can I use?
error:Cross-thread operation not valid: Control 'statusBar1' accessed from a thread other than the thread it was created on.
the code :
public void CalculateGeneration(int nPopulation, int nGeneration)
{
int _previousFitness = 0;
Population TestPopulation = new Population();
for (int i = 0; i < nGeneration; i++)
{
if (_threadFlag)
break;
TestPopulation.NextGeneration();
Genome g = TestPopulation.GetHighestScoreGenome();
if (i % 100 == 0)
{
Console.WriteLine("Generation #{0}", i);
if ( ToPercent(g.CurrentFitness) != _previousFitness)
{
Console.WriteLine(g.ToString());
_gene = g;
statusBar1.Text = String.Format("Current Fitness = {0}", g.CurrentFitness.ToString("0.00"));
this.Text = String.Format("Sudoko Grid - Generation {0}", i);
Invalidate();
_previousFitness = ToPercent(g.CurrentFitness);
}
if (g.CurrentFitness > .9999)
{
Console.WriteLine("Final Solution at Generation {0}", i);
statusBar1.Text = "Finished";
Console.WriteLine(g.ToString());
break;
}
}
}
}
Easiest for reusability is to add a helper function like:
void setstatus(string txt)
{
Action set = () => statusBar1.Text = txt;
statusBar1.Invoke(set);
}
Or with the invokerequired check first:
delegate void settextdelegate(string txt);
void setstatus(string txt)
{
if (statusBar1.InvokeRequired)
statusBar1.Invoke(new settextdelegate(setstatus), txt);
else
statusBar1.Text = txt;
}
Either way the status can then be set like
setstatus("Finished");
For completeness I should add that even better would be to keep your calculating logic separated from your form and raise a status from within your calculating functionality that can be hanled by the form, but that could be completely out of scope here.