Update UI from async task lambda in WinRT - c++

I am writing a small WinRT program to async create a folder and a file. The simplified code is like below:
auto createFolderOp = ApplicationData::Current->LocalFolder->CreateFolderAsync(L"DummyFolder", CreationCollisionOption::OpenIfExists);
create_task(createFolderOp).then([](task<StorageFolder ^> folder)
{
StorageFolder ^tempFolder;
tempFolder = uploadFolder.get();
return tempFolder->CreateFileAsync(L"DummyFile.txt", CreationCollisionOption::ReplaceExisting);
}).then([] (task<StorageFile ^> dummyFile)
{
StorageFile ^file;
file = dummyFile.get();
FileIO::WriteTextAsync(file, L"Dummy Content");
});
During the execution of this code, I want to update my UI on each step. For example I have a textblock and in each step I want to update it to show different text, such as:
Create Folder Succeed...
Create File Succeed...
Write File Succeed...
etc.
How can I access to the UI element from Async task? What is the best practice of doing this?

You need to update the UI from the UI thread. I wrote a post a while ago about getting to the UI thread from different types of Windows Phone apps, it should be applicable to Windows RT Apps as well: http://robwirving.com/2013/07/17/guide-to-getting-to-the-ui-thread-for-any-type-of-windows-phone-8-app/
If you're using Windows Xaml, you should be able to get the Dispatcher from the CoreWindow object and run a lambda using the dispatcher's RunAsync method.
If you're trying to get to the UI thread from a WinRT component, well that's a bit more difficult, but I have a method here: http://robwirving.com/2014/06/02/getting-to-the-ui-thread-from-a-windows-phone-winrt-component/

You can just capture the UI element variable and update it in the lambda body.

Related

Is there terminate event in fluent builder API?

I'm modelling a process in code using Fluent Builder API (https://docs.camunda.org/manual/7.12/user-guide/model-api/bpmn-model-api/fluent-builder-api/) and I want to insert a terminating event (not end event). I cannot manage to find it (in code or in documentation) does it exist? How do I model it?
Unfortunately, this is not directly supported by the fluent model API. But it can be achieved by modifying the eventDefinition:
// plain simple generated bpmn
BpmnModelInstance bpmn = Bpmn.createExecutableProcess()
.startEvent()
.serviceTask()
.endEvent().done();
// find the end event instance in the model (might require filtering by id if more than one)
EndEvent endEvent = bpmn.getModelElementsByType(EndEvent.class).stream().findFirst().get();
// create an EventDefinition for terminate
TerminateEventDefinition terminateEventDefinition = bpmn.newInstance(TerminateEventDefinition.class);
// add that event definition to the endEvent instance
endEvent.getEventDefinitions().add(terminateEventDefinition);

Cancelling an upload task

I've done some reading regarding the Azure SDK and in order to cancel a task you seemingly need to pass in a cancellation_token.
My upload code is very simple:
azure::storage::cloud_block_blob blockBlob = container.get_block_blob_reference(fileLeaf.wstring());
auto task = blockBlob.upload_from_file_async(fullFilePath);
However, some files I upload are potentially very large, and I would like to be able to cancel this operation. I'll probably also likely use continuations and would need all those cancelling too, if that's possible.
The problem I'm having is I can't see any way of attaching a cancellation_token to the task.
Any pointers?
There is a sample code using PPL library, I refered to it and changed the code for canceling task using PPLX library within C++ REST SDK which be used for Azure Storage SDK for C++, please try the code below.
/* Declare a cancellation_token_source and get the cancellation_token,
* please see http://microsoft.github.io/cpprestsdk/classpplx_1_1cancellation__token__source.html
*/
#include <pplxtasks.h>
cancellation_token_source cts;
auto token = cts.get_token();
//Pass the cancellation_toke to task via then method, please see https://msdn.microsoft.com/en-us/library/jj987787.aspx
task.then([]{}, token).wait();
// Cancel the task
cts.cancel();
Hope it helps.

ember-data 2.0 and Offline

I am creating a new ember app. I want to use the newest version of ember-data. (ember-data 2.0). I want it to be a mobile webapp. Therefore it must handle variable network access and even offline.
I want it to store all data locally and use that data when it goes offline so the user gets the same experience regardless of the network connectivity.
Is ember-data 2.0 capable of handling the offline case? Do I just make an adapter that detects offline/online and then do....?
Or do I have to make my own in-between layer to hide the offline handling from ember-data?
Are there any libraries out there that has this problem solved? I have found some, but are there any that is up to date with the latest version of ember-data?
If device will go offline and user will try to transition to route, for which model is not loaded yet, you will have an error. You need to handle these situations yourself. For example, you may create a nice page with error message and a refresh button. To do this, you need:
First, In application route, create error action (it will catch errors during model hook), and when error occurs, save transition in memory. Do not try to use local storage for this task, it will save only properties, while we need an actual transition object. Use either window.failedTransition or inject in controllers and routes a simple object, which will contain a failed transition.
actions: {
error: function (error, transition) {
transition.abort();
/**
* You need to correct this line, as you don't have memoryStorage
* injected. Use window.failedTransition, or create a simple
* storage, Iy's up to you.
*/
this.get('memoryStorage').set('failedTransition', transition);
return true; //This line is important, or the whole idea will not work
}
}
Second, Create an error controller and template. In error controller define an action, retry:
actions: {
retry: function () {
/**
* Correct this line too
*/
var transition = this.get('memoryStorage').getAndRemove('failedTransition');
if (transition !== undefined) {
transition.retry();
}
}
}
Finally, In error template display a status and an error text (if any available) and a button with that action to retry a transition.
This is a simple solution for simple case (device gone offline just for few seconds), maybe you will need something way more complex. If you want your application to fully work without a network access, than you may want to use local storage (there is an addon https://github.com/funkensturm/ember-local-storage) for all data and sync it with server from time to time (i.e sync data every 10 sec in background). Unfortunately I didn't try such things, but I think it is possible.

C++ create cef object in custom thread

I'm tring to create a javascript object to pass it to a function-callback like following:
void MyClass::ThreadTaskOnSuccess(CefRefPtr<CefV8Value> callback, CefRefPtr<CefV8Context> callbackCtxt)
{
if (!CefCurrentlyOn(TID_UI))
{
// switch to UI thread
CefPostTask(TID_UI, NewCefRunnableMethod(this, &NewDownloadObject::CreateTempDownloadOnSuccess, callback, callbackCtxt));
return;
}
// String creation works perfect!
// CefRefPtr<CefV8Value> executionResult = CefV8Value::CreateString("test");
// "Access violation" will be thrown
CefRefPtr<CefV8Value> executionResult = CefV8Value::CreateObject(NULL);
executionResult->SetValue("size", CefV8Value::CreateInt(123), V8_PROPERTY_ATTRIBUTE_NONE);
executionResult->SetValue("fileName", CefV8Value::CreateString("some name of file"), V8_PROPERTY_ATTRIBUTE_NONE);
CefV8ValueList args;
args.push_back(executionResult);
CefRefPtr<CefV8Value> retval;
CefRefPtr<CefV8Exception> exception;
if (callback->ExecuteFunctionWithContext(callbackCtxt, callbackCtxt->GetGlobal(), args, retval, exception, false))
{
if (exception.get())
{
throw CFdmException(exception->GetMessage().c_str());
}
else
{
// Execution succeeded.
}
}
}
But CefV8Value::CreateObject(NULL) always returns null result. I guess that happens because the code is run in a custom thread, for some tasks have to be performed in a special thread.
Am I right? And how to switch to cef thread to work with V8 engine and syncronise with it?
Am I wrong? And why V8 creates a null object?
Updated
I have added UI thread switching. After that I always have "Access violation reading location" exception in cef_v8value_create_object like in the Hzmy's quiestion.
In short: you must access to V8 only from valid thread.
You probably miss How to use V8 JavaScript integration in client applications wiki page.
With CEF3 WebKit and JS execution run in a separate renderer process. The main thread in a renderer process is identified as TID_RENDERER and all V8 execution must take place on this thread. JS APIs that communicate between the browser and renderer processes should be designed using asynchronous callbacks. See http://www.chromium.org/developers/design-documents/extensions/how-the-extension-system-works/api-pattern-design-doc for an example.
The chromiumembedded documentation contains following:
So you should switch on the right contect before your actions with javascript model.
If V8 is not currently inside a context, or if you need to retrieve and store a reference to a context, you can use one of two available CefV8Context static methods. GetCurrentContext() returns the context for the frame that is currently executing JS. GetEnteredContext() returns the context for the frame where JS execution began. For example, if a function in frame1 calls a function in frame2 then the current context will be frame2 and the entered context will be frame1.
Arrays, objects and functions may only be created, modified and, in the case of functions, executed, if V8 is inside a context. If V8 is not inside a context then the application needs to enter a context by calling Enter() and exit the context by calling Exit(). The Enter() and Exit() methods should only be used:
When creating a V8 object, function or array outside of an existing context. For example, when creating a JS object in response to a native menu callback.
When creating a V8 object, function or array in a context other than the current context. For example, if a call originating from frame1 needs to modify the context of frame2.
So that's why I couldn't create an object but was able to create js strings.
Also you could see the general usage example.
And the following code solves the problem:
if (callbackCtxt.get() && callbackCtxt->Enter())
{
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(NULL);
// call ExecuteFunctionWithContext and perform other actions
callbackCtxt->Exit();
}

making use of libcurl progress data

In Xcode set up a stack of curl_easy_setopt-functions for uploading a file to a server/API, and (after a lot of trial and error) it all works like a charm. After going through several other Q&As i also managed to set up an easy CURLOPT_PROGRESSFUNCTION that looks like this:
static int my_progress_func(void *p,
double t,
double d,
double ultotal,
double ulnow)
{
printf("(%g %%)\n", ulnow*100.0/ultotal);
// globalProgressNumber = ulnow*100.0/ultotal;
return 0;
}
As the upload progresses "0%.. 16%.. 58%.. 100%" is output to the console; splendid.
What i'm not able to do is to actually USE this data (globalProgressNumber) eg. for my NSProgressIndicator; CURL kind of hijacks my App and doesn't allow any other input/output until the progress is complete.
I tried updating IBOutlets from my_progress_func (eg. [_myLabel setStringValue:globalProgressNumber];) but the static int function doesn't allow that.
Neither is [self] allowed, so posting to NSNotificationCenter isn't possible:
[[NSNotificationCenter defaultCenter]
postNotificationName:#"Progressing"
object:self];
My curl function runs from my main class/ window (NSPanel).
Any good advice on how to achieve a realtime/ updating element on my .xib?
CURL [...] doesn't allow any other input/output until the progress is complete.
Are you calling curl_easy_perform from the main thread? If yes, you should not do that since this function is synchronous, i.e it blocks until the transfer finishes.
In other words long running tasks (e.g with network I/O) must run on a separate thread, while UI code (e.g. updating the text of a label) must run on the main thread.
how to achieve a realtime/updating element
You should definitely take care to perform the curl transfer in a separate thread.
This could be easily achieved by wrapping this into an NSOperation with a custom protocol to notify a delegate of the progress (e.g your view controller):
push your operation into an NSOperationQueue,
the operation queue will take care to detach the transfer and run it into an another thread,
on the operation side, you should still use the progress function and set the operation object as the opaque object via the CURLOPT_PROGRESSDATA curl option. By doing so, each time the progress function is called you can retrieve the operation object by casting the void *clientp opaque pointer. Then notify the delegate of the current progress in the main thread (e.g with performSelectorOnMainThread) to make sure you can perform UI updates such as refreshing your NSProgressIndicator.
As an alternative to an NSOperation you can also use Grand Central Dispatch (GCD) and blocks. If possible, I greatly recommend you to work with BBHTTP which is a libcurl client for iOS 5+ and OSX 10.7+ (BBHTTP uses GCD and blocks).
FYI: here's an example from BBHTTP that illustrates how to easily perform a file upload with an upload progress block - this is for iOS but should be directly reusable for OS X.