locked
How to integrate WinRT asynchronous tasks into existing synchronous libraries?

    Question

  • We have a long established, greatly multiplatform codebase that is currently being ported to WinRT. One of the challenges we're facing is how to handle WinRT's asynchronous style.

    For example, we are unsure how to handle WinRT's async file operations. Unsurprisingly, our codebase's API is synchronous. A typical example is our File::Open function which attempts to open a file and return with success or failure. How can we call WinRT functions and yet keep the behavior of our functions the same?

    Note that we are unfortunately constrained by legacy: we cannot simply go and change the API to become asynchronous.

    Thanks!

    Wednesday, October 10, 2012 3:20 PM

Answers

  • You may synchronize an asynchronous operation by something like this..

    	volatile bool asyncOperationCompleted = false;
    
    	 task<void>( AsyncTask( ... ) ).then([&asyncOperationCompleted] (task<void> previousTask) { 
    		 try{
    			previousTask.get(); 
    			asyncOperationCompleted = true;
    		 } catch(Exception e) { 
    			 asyncOperationCompleted = true;
    		 });
    
    	while( false == asyncOperationCompleted ) 
    		CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneIfPresent);

    • Proposed as answer by Jesse Jiang Thursday, October 11, 2012 7:44 AM
    • Marked as answer by Jesse Jiang Tuesday, October 16, 2012 6:29 AM
    Thursday, October 11, 2012 2:20 AM

All replies

  • First of all, try to use WinRT's asynchronous style. It facilitates, keeping your application always responsive and will also get several other advantages of WinRT asynchronous implementation.

    I think, you can meet your requirements several ways, like

    1. You may use task chain for maintaining the sequence of several asynchronous operation like  yourAsyncTask.then(…).then(…).then(…);

    2. You may use wait() function of a task for waiting until the task is finished. For instance, following asynchronous function executes synchronously

    create_task( FileIO::WriteTextAsync(file, "String to write") ).then([this](task<void> writeTask)
              {
                  try
                  {
                     writeTask.get();
    	         // Text Written Successfully.
                  }
                  catch(COMException^ ex)
                    {
                     //Failed to write Text.
                    }
                }).wait();  //Here it waits until asynchronous operation completed and it returns the result(success/failure) of asynchronous task.

    3. You may also synchronize an asynchronous task using several synchronization functions like following..

    HANDLE htest=CreateEventEx( NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS ); ResetEvent(htest);

    task<void>( OpenAsync( ... ) ).then([this] (task<void> previousTask) { try{

    previousTask.get(); SetEvent(htest); //Success } catch(Exception e) { SetEvent(htest); //Failure } WaitForSingleObjectEx(htest, INFINITE, TRUE);

    Note: In case of 2 & 3 you should run this sync procedure in a separate worker thread in WinRT, because UI thread does not expect any blocking.


    Wednesday, October 10, 2012 5:09 PM
  • I think create_task creates a new thread. I tried to use empty async operation to create_task but not success. Something like

    create_task().then[this](task<void> myTask){...});

    or simpler

    create_task().then[]()

    {

    ......

    create_task().then[]()

    {             

    ......

    });

    });

    Unfortunately it generated compile error. Without an Async call create_task will not generate a sync.

     


    Charlie Chang L

    Wednesday, October 10, 2012 7:30 PM
  • You may synchronize an asynchronous operation by something like this..

    	volatile bool asyncOperationCompleted = false;
    
    	 task<void>( AsyncTask( ... ) ).then([&asyncOperationCompleted] (task<void> previousTask) { 
    		 try{
    			previousTask.get(); 
    			asyncOperationCompleted = true;
    		 } catch(Exception e) { 
    			 asyncOperationCompleted = true;
    		 });
    
    	while( false == asyncOperationCompleted ) 
    		CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneIfPresent);

    • Proposed as answer by Jesse Jiang Thursday, October 11, 2012 7:44 AM
    • Marked as answer by Jesse Jiang Tuesday, October 16, 2012 6:29 AM
    Thursday, October 11, 2012 2:20 AM