Dart: update UI during long computation - dart

I have a small dart script which I intend to use in the following way:
CanvasElement canvas;
void main() {
canvas = querySelector('#canvas');
querySelector('#start-button').onClick.listen((_) => work());
}
void work() {
var state; // some state of the computation
for (int i = 0; i < /*big number*/; i++) {
// do some long computation
render(state); // display intermediate result visualisation on canvas
}
}
void render(var state) {
canvas.context2D.... // draw on canvas based on state
}
that is listen for click on a button and on that click execute some long computation and from that computation display some intermediate results on the canvas live as the computation progresses.
However, this does not work - the canvas is updated only once after the whole computation completes.
Why is that? How should I arrange my code to work in a live, responsive way?

One of solutions would be to put parts of your long computation into dart's event loop, i.e. queuing computation by waiting for a future it immediately return.
Please, see sample on DartPad.
But if you have lots of heavy computations, I think it would be better to start a new isolate and communicate with it about it's state.
Update
Here is almost, not exactly the same, work function, rewritten without using await, maybe it would be a bit clearer how it works:
for (int i = 0; i < 200; i++) {
new Future(()=>compute(i)).then((double result)=>render(i+result*50));
}
Here, we are actually creating 200 futures, queuing them into event loop (Future constructor does that), and registering a personal callback for each one.

Related

How to go to next within for each loop

I recently needed to modify someone's code that used multiple continue cases in a for each. The addition was a new control loop inside the for each, which promptly broke the continue logic. Is there a good way to get the next list item in a such a loop without rewriting all of the continue cases?
// Additional control loops within the member function which cannot be
// turned into functions due to native C++ data types.
{
for each(KeyValuePair<String^,String^> kvp in ListOfItems) {
do { // new condition testing code
// a bunch of code that includes several chances to continue
} while (!reachedCondition)
}
}
continue and break go to the inner most control loop. I've used the iterator within a for loop. So depending upon what your ListOfItems is (i.e. SortedList or Dictionary ...) you might be able to iterate instead of continue.
int i=0;
Dictionary^ d = gcnew Dictionary<string, string>();
for (IEnumerator<KeyValuePair<string, string>>^ e = d->GetEnumerator();i< d->Count;i++) {
// do stuff
e->MoveNext();
}

Future functions in a loop not working

I want to execute same future function with different values. The order is not important. But I want to execute some functions after the above future function. My idea is
addrMapList.forEach((addrMap){ //length is 3
exeQuery(sql).then((result){
print(result);
});
});
print('All finished');
// other actions
Future exeQuery(String sql){
var c=new Completer();
Random rnd=new Random();
c.complete(rnd.nextInt(100));
return c.future;
}
But the result is
All finished
72
90
74
But I need a result like
72
90
74
All finished
How can this implement in dart.. Please help.
Here is modified version of your sample to work as you expected it to.
First of all, you should understand how asynchronous code works, and why it was not in your case:
When you write constructions like <some future>.then( (){...} ); you are not immediately running code defined inside .then( ). You just defining a callback, to be called later. So, in your code, you're defined 3 callbacks, and then, immediately, printed "All finished", at the time when no of your futures even started to work. At this moment they are just sitting in dart's event loop and waiting for a chance to be executed. And they will get that chance only when you finish execution of current code, and not a moment earlier, because Isolate is run as a single thread.
I used Future.wait() to wait for multiple futures because you said order is not important. This is more efficient then waiting Futures one by one. But if order is important, you have to use Future.forEach(), it will not start execution of second Future until first one is completed.
One more thing in your code is that your function returning a Future is actually synchronous, because it always returns already completed Future. This is also changed in dartpad sample above to better visualize how asynchronous code works.
forEach can't be used this way. Use await for instead (the enclosing function needs to be async)
Future someFunc() async {
await for (var addrMap in addrMapList) {
var result = await exeQuery(sql);
print(result);
}
// other action
}

Using polymer's `.job` in polymer.dart

In Polymer there is a this.job() function that handles the delayed processing of events. How do you access this functionality from polymer.dart?
#override
void attached() {
super.attached();
dom.window.onMouseMove.listen(mouseMoveHandler);
}
PolymerJob mouseMoveJob;
void mouseMoveHandler(dom.MouseEvent e) {
print('mousemove');
mouseMoveJob = scheduleJob(mouseMoveJob, onDone, new Duration(milliseconds: 500));
}
void onDone() {
print('done');
}
If the job isn't rescheduled for 500ms it is executed.
In polymer this is often used during initialization when
xxxChanged(old);
is called several times succinctly because xxx is updated on changes from several other states which are initialized one after the other but it is enough when xxxChanged is executed for the last update (a much shorter timeout should be used then like 0-20 ms depending whether xxxChanged is only called from sync or also from async code.
Another situation where I used this pattern (but not using PolymerJob) is where an #observable field is bound to a slider <input type="range" value='{{slider}}'>.
This invokes sliderChanged(oldVal, newVal) very often in a short interval when you move the knob. The execution of the update is expensive and can't be finished between two such calls see http://bwu-dart.github.io/bwu_datagrid/example/e04_model.html for an example.
Without some delayed execution this would be very cumbersome to use.
Try using Future:
doJob() => print('hi');
new Future(doJob).then((_) => print('job is done'));
Here are the docs for the Future class.

C++ equivalent of .NET's Task.Delay?

I'm writing a C++/CX component to be consumed by Window's store Apps. I'm looking for a way to accomplish what Task.Delay(1000) does in C#.
Old Question, but still unanswered.
You can use
#include <chrono>
#include <thread>
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
This will need C++11, which shouldn't be a problem when using C++/CX.
After one year of using C++/CX, I have a general and reasonably correct answer to this question.
This link (from the Visual C++ Parallel Patterns Library documentation) includes a snippet for a function called complete_after(). That function creates a task that will complete after the specified number of milliseconds. You can then define a continuation task that will execute afterwards:
void MyFunction()
{
// ... Do a first thing ...
concurrency::create_task(complete_after(1000), concurrency::task_continuation_context::use_current)
.then([]() {
// Do the next thing, on the same thread.
});
}
Or better yet, if you use Visual C++'s coroutines capabilities simply type:
concurrency::task<void> MyFunctionAsync()
{
// ... Do a first thing ...
co_await complete_after(1000);
// Do the next thing.
// Warning: if not on the UI thread (e.g., on a threadpool thread), this may resume on a different thread.
}
You could create a concurrency::task, wait for 1000 time units and then call the ".then" method for the task. This will ensure that there is at least a wait of 1000 time units between the time you created the task and between the time it gets executed.
I'm not going to claim to be a wizard - I'm still fairly new to UWP and C++/CX., but what I'm using is the following:
public ref class MyClass sealed {
public:
MyClass()
{
m_timer = ref new Windows::UI::Xaml::DispatcherTimer;
m_timer->Tick += ref new Windows::Foundation::EventHandler<Platform::Object^>(this, &MyClass::PostDelay);
}
void StartDelay()
{
m_timer->Interval.Duration = 200 * 10000;// 200ms expressed in 100s of nanoseconds
m_timer->Start();
}
void PostDelay(Platform::Object^ sender, Platform::Object ^args)
{
m_timer->Stop();
// Do some stuff after the delay
}
private:
Windows::UI::Xaml::DispatcherTimer ^m_timer;
}
The main advantage over other approaches is that:
it's non-blocking
You're guaranteed to be called back on the XAML UI thread

How to do several asynchronous I/O actions in Dart cleanly (Isolates)?

In Dart, there is a concept of Isolates. I have an application (that I'm experimenting in Dart) that has lots of asynchronous IO where each call (they are database calls) are dependent on the previous one. So I have ended up in a nested callback hell.
I was wondering if Isolates could solve that nested callback soup, but it looks a bit verbose and I'm not sure if it fits it well.
There are also Generators proposed in the next ECMAScript Harmony which could solve these things, but how would you currently do lots of asynchronous IO in Dart in a clean way?
You can use Future's and Completers to chain work together. The following future returns the result of a 'ls' command from a process:
Future<String> fetch(String dir) {
final completer = new Completer();
Process process = new Process.start('ls', [dir]);
process.exitHandler = (int exitCode) {
StringInputStream stringStream = new StringInputStream(process.stdout);
stringStream.dataHandler = () {
String content = stringStream.read();
completer.complete(content);
process.close();
};
};
process.errorHandler = (var error) {
completer.completeException(error);
return true;
};
return completer.future;
};
which you can then chain together like this:
fetch('/').then((val) => fetch("/usr").then((val) => fetch("/tmp")));
Not the most pretty solution but this is what I get by with now.

Resources