-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't join a canceled task #64
Comments
According to |
@elizarov However I see why it is confusing as |
@blastrock so to get execution synchronized you can need some different way, consider the following
Notice that it this solution is not the same as |
The difference in behaviour between |
Thanks for the answer. If I may, even if you rename join to make it less confusing, I think a join() API would be very useful. I came up with a workaround similar to this: @Volatile
var keepRunning = true
val job = async(CommonPool) {
while (keepRunning);
Thread.sleep(1000)
System.out.println("end of async")
}
keepRunning = false
job.join()
System.out.println("end of test") Both your workaround and mine seem cumbersome to me. It happens very often to me that I need to cancel a coroutine and be sure it is finished to ensure there is no race condition, for example when I am shutting down, or if I want to start a new coroutine which will access the same data as the one that is running. I think the join() primitive would be very useful with cancelation, and probably not much harder to implement than what you have now. |
The reason However, the workarounds presented so far are not ideal either. Channel is too heavy-weight for such light-weight task as tracking job termination. I'll think on how it can be done easier. |
@blastrock As a better workaround for cases where you need to wait until the task is fully terminated I'd suggest the following utility function:
You can use it instead of Note, that is the next release of |
@elizarov exception also need to be propagated, so it requires a lot of preparation to get this fake job work as intended |
I would also highly recommend using an |
Indeed it would introduce a new state in the Job class, but maybe this state doesn't need to be exposed. I have yet to find a use-case, in kotlin or another language, where I need to know if (or when) a job is "completed", I usually only need to know when it is "terminated" (as you called it). Of course the "canceled but running"-state must still be exposed inside the coroutine through the isActive call. Maybe I can make a wrapper with a workaround, but maybe I would need to expose my own Job class to do that. I'll think about it. As for the Actor pattern, I don't think I can implement job cancelation easily with it. But the one-task-at-a-time guarantee is there indeed. |
I've pushed the corresponding changes to the It is important to note, that in current implementation a cancelled coroutine is doomed to complete exceptionally. Even if Note, that the naming of various states (see docs on |
@elizarov Thanks a lot for working on this issue, it is truly appreciated. I am also facing a similar issue. I'm trying to figure out whether or not it's best for us to wait on this fix or use one of the workaround. |
I plan to get it released soon (this or next week) |
@elizarov I'm thinking. Maybe we don't need to change the behavior of join. Or perhaps, maybe there could be another method that continues to behave like the current implementation. Meanwhile. What will be the behavior in both situations below with the new implementation.
Thank you. |
The reason to change the implementation of |
Released in version 0.17 |
Is there a way to get old behavior in the new version? Maybe with another method instead of For example if I'm wrapping coroutine around blocking task that is outside my control (task itself cannot be cancelled mid-execution) and I cancel the coroutine, I would want to return execution immediately and let that dangling blocking function just finish in the background instead of blocking everything. |
You can just use |
Yes, but what if cancel is triggered by another thread? For example, on Android, coroutine is |
You can install callback that gets triggered as soon as cancel is invoked with
|
that sounds like good workaround. Thanks! |
Hi,
In the following code, I want to make sure my code blocks until the task is really finished:
The result is that I see "end of test" instantly, and "end of async" appears a second after, even though I asked to join() the task. Am I misusing the library or is this a bug?
The text was updated successfully, but these errors were encountered: