I was trying to find a solution to run different task in different threads (depends/independents)
I have scenario where I need to run one task (which internally runs a server) in different thread before running another task (test, depends on above server) in gradle, after 2nd task completed I need to kill first task.
Again, same as above scenario, run another set of server/test/kill tasks.
task exp{
doFirst{
run1stServerTask.execute()
}
def pool = Executors.newFixedThreadPool(5)
try {
def defer = { closure -> pool.submit(closure as Callable) }
defer {
run1stTest.execute()
// After tests are finished, kill 1st server tasks
}
defer {
run2ndServerTask.execute()
}
defer {
run2ndTest.execute()
// After tests are finished, kill 2nd server tasks
}
}
finally {
pool.shutdown()
}
}
Hope, All above make sense... I am open for another approach if its possible in build.gradle.
Related
In my Android application I have code that should run periodically in its own coroutine and should be cancelable.
for this I have the following functions:
startJob(): Initializes the job, sets up invokeOnCompletion() and starts the work loop in the respective scope
private fun startJob() {
if (::myJob.isInitialized && myJob.isActive) {
return
}
myJob= Job()
myJob.invokeOnCompletion {
it?.message.let {
var msg = it
if (msg.isNullOrBlank()) {
msg = "Job stopped. Reason unknown"
}
myJobCompleted(msg)
}
}
CoroutineScope(Dispatchers.IO + myJob).launch {
workloop()
}
}
workloop(): The main work loop. Do some work in a loop with a set delay in each iteration:
private suspend fun workloop() {
while (true) {
// doing some stuff here
delay(setDelayInMilliseconds)
}
}
myJobCompleted: do some finalizing. For now simply log a message for testing.
private fun myJobCompleted(msg: String) {
try {
mainActivityReference.logToGUI(msg)
}
catch (e:Exception){
println("debug: " + e.message)
}
}
Running this and calling myJob.Cancel() will throw the following exception in myJobCompleted():
debug: Only the original thread that created a view hierarchy can touch its views.
I'm curious as to why this code isn't running on the main thread, since startJob() IS called from the main thread?
Furthermore: is there a option similar to using a CancellationTokenSource in c#, where the job is not immediately cancelled, but a cancellation request can be checked each iteration of the while loop?
Immediately breaking off the job, regardless of what it is doing (although it will pretty much always be waiting for the delay on cancellation) doesn't seem like a good idea to me.
It is not the contract of Job.invokeOnCompletion to run on the same thread where Job is created. Moreover, such a contract would be impossible to implement.
You can't expect an arbitrary piece of code to run on an arbitrary thread, just because there was some earlier method invocation on that thread. The ability of the Android main GUI thread to execute code submitted from the outside is special, and involves the existence a top-level event loop.
In the world of coroutines, what controls thread assignment is the coroutine context, while clearly you are outside of any context when creating the job. So the way to fix it is to explicitly launch(Dispatchers.Main) a coroutine from within invokeOnCompletion.
About you question on cancellation, you can use withContext(NonCancellable) to surround the part of code you want to protect from cancellation.
When I run the following (simplified) code on a low powered server with only 1 core:
implicit val context: ExecutionContextExecutor = scala.concurrent.ExecutionContext.global
Future(blocking {
while (true) {
java.lang.Thread.sleep(1000)
println("thread 1")
}
})
while (true) {
java.lang.Thread.sleep(1000)
println("main")
}
Only "main" shows up in the logs. If I increase the server to have more cores, then it works. What am I doing wrong? How to make Scala/Java run every thread even when there are limited cores?
My understanding is that the runtime should use some logic to execute one thread for a bit, then switch to the other thread.
scalaVersion := "2.12.12"
After a bit of playing around, I found that if I use ExecutionContext.fromExecutor(Executors.newFixedThreadPool(30)) for my EC it works. So something about the way I understand the global EC & blocking must be wrong.
I am not able to replicate this problem. Even on a single core there should be at least one thread available when using ExecutionContext.global because the default calculations is
numThreads = Runtime.getRuntime.availableProcessors * 1
and so
Future(blocking {
while (true) {
java.lang.Thread.sleep(1000)
println("thread 1")
}
})
should execute in that thread whilst
while (true) {
java.lang.Thread.sleep(1000)
println("main")
}
should execute in the main thread.
Note even with just a single thread available, if you consistently used blocking {} then new threads would still be spawned up to maxExtraThreads
scala.concurrent.context.maxExtraThreads = defaults to "256"
Hence the problem likely lies somewhere else.
I want to run each TPL task in a separate thread (the idea is having TPL advantages in the same time with working with a separate threads). It looks like this task scheduler is exactly what I'm looking for: ThreadPerTaskScheduler .
I made several local tests and I see that it works as I expected including the ability to call Task.WaitAll.
var task = Task.Factory.StartNew(() =>
{
Thread.Sleep(10000);
}, CancellationToken.None, TaskCreationOptions.None, new ThreadPerTaskScheduler());
Task.WaitAll(task);
But, I have a question about this line from the task scheduler implementation:
protected override void QueueTask(Task task)
{
new Thread(() => TryExecuteTask(task)) { IsBackground = true }.Start();
}
as I see, we just create a new thread without saving any reference on this thread anywhere. If so, how does Task.WaitAll work?
I was trying to update the recycler view content from a background thread in Kotlin. I am not using AsyncTask.
Here is my code, i want to know if there is any better way than this:
In my MainActivity, i have progressThread as a member variable.
var progressThread = Thread()
Then in my method where i want to run the thread first i am defining it...like
progressThread = Thread (
Runnable {
kotlin.run {
try {
while (i <= 100 && !progressThread.isInterrupted) {
Thread.sleep(200)
//Some Logic
runOnUiThread {
//this runs in ui thread
}
i++
}
}catch (e:InterruptedException){
progressThread.interrupt()
}
}
})
after that i am starting it in the same method as
progressThread.start()
and for stopping it, i have a listener to cancel the progress and in the callback of that listener, i have written:
progressThread.interrupt()
Updated
Coroutines are stable now,: https://kotlinlang.org/docs/reference/coroutines-overview.html
Old Answer
Yes, you can do this using doAsync from kotlin anko library that is fairly simple and easy to use.
add following line in module level gradle file:
compile "org.jetbrains.anko:anko-commons:0.10.0"
Code example:
val future = doAsync {
// do your background thread task
result = someTask()
uiThread {
// use result here if you want to update ui
updateUI(result)
}
}
code block written in uiThread will only be executed if your Activity or Fragment is in foreground mode (It is lifecycle aware). So if you are trying to stop thread because you don't want your ui code to execute when Activity is in background, then this is an ideal case for you.
As you can check doAsync returns a Future object so you can cancel the background task, by cancel() function:
future.cancel(true)
pass true if you want to stop the thread even when it has started executing.
If you have more specialised case to handle stopping case then you can do the same thing as in your example.
You can use Kotlin Coroutines also but its in Experimental phase, still you can try it out: https://kotlinlang.org/docs/reference/coroutines.html
This a simplification and narrowing to another of my questions: Need help parallel traversing a dag in D
Say you've got some code that you want to parallelize. The problem is, some of the things you need to do have prerequisites. So you have to make sure that those prerequisites are done before you add the new task into the pool. The simple conceptual answer is to add new tasks as their prerequisites finish.
Here I have a little chunk of code that emulates that pattern. The problem is, it throws an exception because pool.finish() gets called before a new task is put on the queue by the worker thread. Is there a way to just wait 'till all threads are idle or something? Or is there another construct that would allow this pattern?
Please note: this is a simplified version of my code to illustrate the problem. I can't just use taskPool.parallel() in a foreach.
import std.stdio;
import std.parallelism;
void simpleWorker(uint depth, uint maxDepth, TaskPool pool){
writeln("Depth is: ",depth);
if (++depth < maxDepth){
pool.put( task!simpleWorker(depth,maxDepth,pool));
}
}
void main(){
auto pool = new TaskPool();
auto t = task!simpleWorker(0,5,pool);
pool.put(t);
pool.finish(true);
if (t.done()){ //rethrows the exception thrown by the thread.
writeln("Done");
}
}
I fixed it: http://dpaste.dzfl.pl/eb9e4cfc
I changed to for loop to:
void cleanNodeSimple(Node node, TaskPool pool){
node.doProcess();
foreach (cli; pool.parallel(node.clients,1)){ // using parallel to make it concurrent
if (cli.canProcess()) {
cleanNodeSimple(cli, pool);
// no explicit task creation (already handled by parallel)
}
}
}