I have the following dart code in the latest Dart dev release (SDK 1.9.0-dev.8.0):
main() async {
var i = await testMethod(1);
var j = await testMethod(2);
var k = await testMethod(3);
}
int testMethod (int x) {
var breakpoint = 'breakpoint is set here';
print(x);
return(x);
}
When I put a breakpoint in the first statement of the testmethod, the breakpoint only gets hit for the second call and third call, never for the first call. The console prints 1, then the debugger stops in at the breakpoint for the second call.
Is this still a bug in the async/await debugging or am I missing something here?
Related
I'm going through Kyle Simpson's Rethinking Async on Frontend Masters, and in the lecture on async generators, there is an example of calling .next() recursively. The gist of it goes as follows:
function *main() {
var x = (yield setTimeout(function() {return a.next(2)},0));
console.log(x)
}
var a = main();
a.next();
Which prints 2
Correct me if I'm wrong. What I understand from this is that the encounter with yield pauses execution and waits for a value. The functionRef from setTimeout is placed on the stack and is called next, returning the value 2.
Essentially this is the same as
function *main() {
var x = yield ;
console.log(x);
}
var a = main();
a.next()
a.next(2)
Now I try to do the following, thinking the result will be the same:
function *main() {
var x = (yield a.next(2));
console.log(x)
}
var a = main();
a.next();
and it throws the error TypeError: Generator is already running
Why?
Further, I expected this to print 2 but instead in prints undefined
function *main() {
var x = yield 2;
console.log(x)
}
var a = main();
a.next()
a.next()
Evidently, yield behaves rather a bit differently when assigned to a variable versus when it is not, but I can't quite put a finger on it.
I wrote a torrent download demo , look like this:
var peers....
for(var i =0;i < length;i++){
var peer = peers[i];
peer.start((List<int> data){
_downloadFile.write(begin,end,data);
});
}
I mean that there are mutiple peer try to access the _file.
`_downloadFile` code looks like this:
....
var _access = _file.open(mode:FileMode.writeOnlyAppend);
...
Future write(int begin,int end, List<int> block) async{
....
await _access.setPosition(begin);
await _access.writeFrom(block);
....
}
And it will throw exception : FileSystemException: An async operation is currently pending
I think the reason is that different fork invoke setPosition, so I try to make each fork to wait the write operation over:
`_downloadFile` code look like this:
....
var _access = _file.open(mode:FileMode.writeOnlyAppend);
var _lock;
...
Future write(int begin,int end, List<int> block) async{
if(_lock != null) await _lock;
var c = Completer();
_lock = c.future;
....
await _access.setPosition(begin);
await _access.writeFrom(block);
c.complete();
....
}
If I understand correctly, when peer recieves data , it will call write method , then it should wait the _lock completed, but I still get FileSystemException.
Now I have to use Stream , with its pause and resume method to avoid this exception.
Can someone tell me what's the problems with the last codes? why the _lock does not work? Does Dart have something like 'object lock'?
Thanks very much!
okay, so I have a controller method which need to make a bunch of soap call to an external service, each one quite heavy. I am trying to do these one in parralel to save some time, but unless I build the async calls from GlobalScope, the deferred are resolved in sequence. Let me show you.
executing the following code
#ResponseBody
#GetMapping(path = ["/buildSoapCall"])
fun searchStations(): String = runBlocking {
var travels: List<Travel> = service.getTravels().take(500)
val deferred = travels
.map {
async() {
print("START")
val result = service.executeSoapCall(it)
print("END")
result
}
}
println("Finished deferred")
val callResults = deferred.awaitAll()
println("Finished Awaiting")
""
}
get me the following console message :
Finished deferred
START-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-END.....
the - is printed by executeSoapCall
As you can see, the deferred are called in sequence.
But if I use GlobalScope, like this :
#ResponseBody
#GetMapping(path = ["/buildSoapCall"])
fun searchStations(): String = runBlocking {
var travels: List<Travel> = service.getTravels().take(500)
val deferred = travels
.map {
GlobalScope.async() {
print("START")
val result = service.executeSoapCall(it)
print("END")
result
}
}
println("Finished deferred")
val callResults = deferred.awaitAll()
println("Finished Awaiting")
""
}
I get the following console message :
Finished Treating
STARTSTARTSTARTSTARTSTARTSTARTSTARTSTARTSTARTSTARTSTARTFinished deferred
START-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART--ENDENDSTARTSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-ENDSTART-END...START-END-END-END-END-END-END-END-END-END-END-END-ENDFinished Awaiting
showing that the Deferred are all starting in parallel. In addition, the treatment time is quite shorter.
I don't really understand why I have this behaviour.
Your call to service.executeSoapCall blocks the thread runBlocking coroutine is running on. You need to start async coroutine on a different thread everytime to get a concurrent behavior. You can achieve that by using a threadpool, e.g., Dispatchers.IO:
...
async(Dispatchers.IO) {
print("START")
val result = service.executeSoapCall(it)
print("END")
result
}
...
or creating a new thread on every call:
...
async(newSingleThreadContext("MyThread")) {
print("START")
val result = service.executeSoapCall(it)
print("END")
result
}
...
GlobalScope works because it uses a ThreadPool by default but you should avoid using it. You can read this article by Roman Elizarov about that topic.
I am trying the async examples from the GNOME project site. I get the follwoing warning which I don't under stand on how to fix.
async.vala:8.2-8.17: warning: delegates with scope="async" must be owned
Code
async double do_calc_in_bg(double val) throws ThreadError {
SourceFunc callback = do_calc_in_bg.callback;
double[] output = new double[1];
// Hold reference to closure to keep it from being freed whilst
// thread is active.
// WARNING HERE
ThreadFunc<bool> run = () => {
// Perform a dummy slow calculation.
// (Insert real-life time-consuming algorithm here.)
double result = 0;
for (int a = 0; a<100000000; a++)
result += val * a;
output[0] = result;
Idle.add((owned) callback);
return true;
};
new Thread<bool>("thread-example", run);
yield;
return output[0];
}
void main(string[] args) {
var loop = new MainLoop();
do_calc_in_bg.begin(0.001, (obj, res) => {
try {
double result = do_calc_in_bg.end(res);
stderr.printf(#"Result: $result\n");
} catch (ThreadError e) {
string msg = e.message;
stderr.printf(#"Thread error: $msg\n");
}
loop.quit();
});
loop.run();
}
The warning is pointing at the run variable inside the async function. Who or what needs to be owned? The reference to the closure?
The delegate needs to have a well defined owner all the time. The error message is a bit misleading.
To fix it you have to explicitly transfer the ownership from the delegate to the thread constructor:
new Thread<bool>("thread-example", (owned) run);
Instead of
new Thread<bool>("thread-example", run);
See also: https://wiki.gnome.org/Projects/Vala/Tutorial#Ownership
PS: The generated C code is fine in both cases. (at least with valac 0.46.6)
I am using Tessaract's Xamarin Forms Nuget(https://github.com/halkar/Tesseract.Xamarin), and am trying to scan a picture taken by the Android Device. This is the code that I am using:
private async System.Threading.Tasks.Task<string> OCRAsync(byte[] bytes)
{
TesseractApi api;
api = new TesseractApi(this, AssetsDeployment.OncePerInitialization);
await api.Init("bul");
await api.SetImage(bytes);
var detectedText = api.Results(PageIteratorLevel.Block);
result = string.Empty;
if (detectedText != null)
{
foreach (var annotation in detectedText)
{
result = FindWordInDictionary(annotation.Text);
}
}
return result;
}
The method is called from a synchronized method like this:
var task = OCRAsync(data);
result = task.Result;
Whenever the compiler gets to "await api.Init("bul");" the app freezes indefinitely. Do you know what may cause this problem? Thank you.
The problem was that I needed to give a file location in the .init function:
await api.Init(pathToDataFile, "bul");