I'm looking for a simple example of asynchronous code ( preferable in VB with .NET ) to do something like this:
Main()
async Sub1()
async Sub2()
await Sub1()
print "end"
End
Sub1()
for n=1 to 1000
{ do something }
next
End sub
Sub2()
if n=500 in Sub1() then print "Hello"
End sub
An alternative could be:
Main()
async Sub1()
async Sub2()
await Sub1()
print "end"
End
Sub1()
for n=1 to 1000
if n=500 send signal
{ do something }
next
End Sub
Sub2()
if signal is received print "Hello"
End Sub
Related
My rust code is like below.
#[tokio::main]
pub async fn main() {
for i in 1..10 {
tokio::spawn(async move {
println!("{}", i);
});
}
}
When run the code, I expect it to print 1 to 10 in a random sequence.
But it just print some random numbers:
1
3
2
Terminal will be reused by tasks, press any key to close it.
Why this is happenning?
https://docs.rs/tokio/latest/tokio/fn.spawn.html warns that:
There is no guarantee that a spawned task will execute to completion. When a runtime is shutdown, all outstanding tasks are dropped, regardless of the lifecycle of that task.
One solution that should work is to store all of the JoinHandles and then await all of them:
let mut join_handles = Vec::with_capacity(10);
for i in 1..10 {
join_handles.push(tokio::spawn(async move {
println!("{}", i);
}));
}
for join_handle in join_handles {
join_handle.await.unwrap();
}
P.S. In 1..10, the end is exclusive, so the last number is 9. You might want 1..=10 instead. (see https://doc.rust-lang.org/reference/expressions/range-expr.html)
what changes should I do to the following code to get the following output:
Task 1 complete
Task 4 complete
Task 2 complete
Task 3 complete with task 2 data
I currently getting the outputs given below:
Task 1 complete
Task 2 complete
Task 3 complete with task 2 data
Task 4 complete
import 'dart:async';
void main() {
performTasks();
}
void performTasks() async {
task1();
String task2Result = await task2();
task3(task2Result);
task4();
}
void task1() {
String result = 'task 1 data';
print('Task 1 complete');
}
Future<String> task2() async {
Duration threeSeconds = Duration(seconds: 3);
String result;
await Future.delayed(threeSeconds, () {
result = 'task 2 data';
print('Task 2 complete');
});
return result;
}
void task3(String task2Data) {
String result = 'task 3 data';
print('Task 3 complete with $task2Data');
}
void task4() {
String result = 'task 4 data';
print('Task 4 complete');
}
Don't call task4 after waiting for task2.
So:
void performTasks() async {
task1();
task4();
String task2Result = await task2();
task3(task2Result);
}
That looks pretty obvious, so I'm assuming your real problem is more complicated, and you can't move test4() around like that.
In that case, you should not use await. The await ensures that everything written after the await also executes after the awaited future has completed.
Instead you can fall back on the Future API:
void performTasks() { // no `async`
task1();
task2().then(task3); // no `await`
task4();
}
This sets up task2() to run, and when that is done, it calls task3 with the result. It doesn't wait for anything, though, and it executes task4 immediately after setting this up.
The then method on futures takes a callback, and eventually calls that with the result of the future. Here task3 takes one argument, so it can directly be used as that callback.
That assumes that task2's result is directly usable as an argument to task3. If not, and you have to capture the result and manipulate it first, you'd do it as:
void performTasks() { // no `async`
task1();
task2().then((result2) { // still no await here!
var argument3 = manipulate(result2);
// ... and whatever else you want to do
// between task2 completing and task3 starting.
task3(argument3);
});
task4();
}
in performTasks(), you should move task4(); right after task1();.
Let's say I have a synchronous expensive operation:
let SomeExpensiveOp():string=
System.Console.WriteLine"about to begin expensive OP"
System.Threading.Thread.Sleep(TimeSpan.FromSeconds 2.0)
System.Console.WriteLine"finished expensive OP"
"foo"
That I wrap as an async job:
let SomeExpensiveOpAs():Async<string>=async {
return SomeExpensiveOp()}
Now I want to use this expensive operation to combine it with other two:
let SomeExpensiveOpSeq():seq<Async<string>>=
let op = SomeExpensiveOpAs()
seq {
for some in [Bar(); Baz()] do
yield async {
let! prefix = op
let! someAfterWaiting = some
return (String.Concat (prefix, someAfterWaiting))
}
}
The purpose of putting it into a seq<Async<'T>> is to be able to use Async.Parallel this way:
let DoSomething() =
let someAsyncOps = SomeExpensiveOpSeq() |> List.ofSeq
let newOp = SomeExpensiveOpAs()
let moreAsyncOps = (newOp::someAsyncOps)
let allStrings = Async.RunSynchronously(Async.Parallel moreAsyncOps)
for str in allStrings do
Console.WriteLine str
Console.WriteLine()
However, this makes SomeExpensiveOp to be executed three times. I would expect the second time to be executed an extra time because of the newOp call above, but I was expecting SomeExpensiveOpSeq to reuse the call to SomeExpensiveOp instead of calling it twice. How can I achieve SomeExpensiveOpSeq to only call SomeExpensiveOp once and reuse that for subsequent results?
The key observation here is that let! is invoking the async expression every time—nothing caches its result. Consider this example where we have expOp : Async<string> but we await it three times in an async expression:
let expOp = SomeExpensiveOpAs()
async {
let! a = expOp
let! b = expOp
let! c = expOp
return [a;b;c]
} |> Async.RunSynchronously
about to begin expensive OP
finished expensive OP
about to begin expensive OP
finished expensive OP
about to begin expensive OP
finished expensive OP
val it : string list = ["foo"; "foo"; "foo"]
You can see the async expensive op gets evaluated each time. If you only want to execute that expensive operation once, you could fully evaluate/await its result and use that instead of awaiting it multiple times:
let SomeExpensiveOpSeq():seq<Async<string>>=
let op = SomeExpensiveOpAs() |> Async.RunSynchronously
seq {
for some in [Bar(); Baz()] do
yield async {
let! someAfterWaiting = some
return (String.Concat (op, someAfterWaiting))
}
}
This will still result in the expensive op being executed twice in your code—once in SomeExpensiveOpSeq and another as a result of being prepended on to moreAsyncOps—but it could be refactored further to a single invocation. Basically, if all subsequent async ops depend on this expensive evaluation, why not evaluate it once/first and then use its value wherever necessary:
let SomeExpensiveOpSeq op : seq<Async<string>>=
seq {
for some in [Bar(); Baz()] do
yield async {
let! someAfterWaiting = some
return (String.Concat (op, someAfterWaiting))
}
}
let DoSomething() =
let newOp = SomeExpensiveOpAs() |> Async.RunSynchronously
let someAsyncOps = SomeExpensiveOpSeq newOp |> Async.Parallel |> Async.RunSynchronously
let allStrings = newOp::(List.ofArray someAsyncOps)
for str in allStrings do
Console.WriteLine str
Console.WriteLine()
> DoSomething();;
about to begin expensive OP
finished expensive OP
foo
foobar
foobaz
I'm dealing with some asynchronous functions and trying to update views. In short I have function 1 with asynchronous function that will return a string to be passed to function 2. I am updating views in both functions, on main thread. It all works but I need to understand if this is correct way.
class A {
var varA = ""
var varB = ""
func f1 (_ completion: #escaping (String) -> void ){
some asynchronous call ... { in
...
DispatchQueue.main.async {
self.varA = "something"
sef.labelA.text = self.varA
completion(self.varA)
}
}
}
func f2 (_ string: String){
another asynchronous call ... { in
...
DispatchQueue.main.async {
self.varB = string
sef.labelB.text = self.varB
}
}
}
// funcation call
f1(completion: f2)
}
Three questions, 1) What is the right way to run a dependent function where there is wait for an asynchronous callback?
2) Is DispatchQueue.main.async needed to update views?
3) Is it ok to call async func in another async callback? Isn't there chance self may be nil in some cases if you are updating views in some escaping function?
I'm going to try helping you according to your questions:
Question 1) There are many right ways and each developer can have its own logic, but in this case, what I personally would probably do is something like this:
class A {
func f1 (_ completion: #escaping (String) -> void ){
some asynchronous call ... { in
...
DispatchQueue.main.async { [weak self] in // 1
guard let strongSelf = self else { return } // 2
let varA = "something" // 3
strongSelf.label.text = varA
completion(varA) // 4
}
}
}
func f2 (_ string: String){
another asynchronous call ... { in
...
DispatchQueue.main.async {
sef.labelB.text = string // 5
}
}
}
// function call
// 6
f1(completion: { [weak self] text in
guard let strongSelf = self else { return }
strongSelf.f2(text)
})
}
1 - Here I'm using [weak self] to avoid retain cycles.
2 - Just unwrapping the optional self, case it's nil, I'll just return.
3 - In your case, it's not really necessary to have class variables, so I'm just creating local variables inside the block.
4 - Finally, I'm calling the completion with the variable containing the string.
5 - I also don't really need to set a class variable in here, so I'm just updating the label text with the string provided as a paramater.
6 - Then, I just need to call the first function and use the completion block to call the second after the first one completes.
Question 2) Yes, you must call DispatchQueue.main to update the view. This way your making sure that your code will be executed in the main thread that is crucial for things interacting with UI because it allow us to have a sincronization point as you can read in Apple's documentation.
Question 3) Using [weak self] and guard let strongSelf = self else { return }, I'm avoiding retain cycles and the cases where self can be nil.
I would like to have a method that dispatches an async task, and returns immediately. I don't need wait for the result.
I'd like something like this to work:
/**
* runs a job and return job id for later montoring.
*/
def int runJob(){
int jobId = createJob() // returns immediately
task{
doSomthingThatTakesSomeTime()
}.then {stepResult-> doSmtgElse(stepResult)}
return jobId
}
In the situation above, the task won't run, as there's no call for .get()
, however, if I DO .get() , the method will not return jobId until task is finished.
How can i dispatch the task and still return immediately?
You can run this example as a Groovy script:
#Grapes(
#Grab(group='org.codehaus.gpars', module='gpars', version='1.2.1')
)
import java.util.concurrent.*
import groovyx.gpars.*
def doSomethingThatTakesSomeTime(){
println "calculating..."
for(long i: 0..100){
Thread.sleep(i)
}
println "*done*"
"Done with doSomethingThatTakesSomeTime"
}
def doSomethingElse(){
for(int x:0..1000) print "."
println "doSomethingElse done."
}
/**
* runs a job and return job id for later montoring.
*/
def runJob(){
GParsPool.withPool(){
Future future = createJob() // returns immediately
doSomethingElse() //Do someting else while the async process is running
//Ok, thats done, but the longer runningprocess is still running, return the future
future
}
}
Future createJob(){
//create a new closure, which starts the original closure on a thread pool
Closure asyncFunction = { doSomethingThatTakesSomeTime() }.async()
//Invoke the function, return a Future
asyncFunction()
}
def job = runJob()
//println "\n\nResult is: " + job.get()
If you run the script "as-is", you will see that it runs and the long running job does print *done* indicating it did in fact run to completion, even though the line at the bottom that calls Future.get() is commented out and never called.
If you uncomment the last line, you will see the result printed once complete as a result of calling Future.get()
After reading #pczeus answer and Jérémie B's comment I came up with this:
import static groovyx.gpars.dataflow.Dataflow.task
def int longTask(){
def counter = 0
10.times {
println "longTask_${counter}"
counter++
sleep 10
}
counter
}
def int getSomeString() {
def jobId=55
task {
longTask()
}.then { num -> println "completed running ${num} times" }
return jobId
}
println getSomeString()
sleep 2000
This prints:
longTask_0
55
longTask_1
longTask_2
longTask_3
longTask_4
longTask_5
longTask_6
longTask_7
longTask_8
longTask_9
completed running 10 times
Which is what I intended:
the longTask() is running in the background, the getSomeString() retruns without waiting for the long task, and as long as the program is still running (hence the sleep 2000), even the clause in the 'then' part is executed