locked
Synchronization function(WaitForSingleObjectEx,CreateEventExW,ResetEvent) problem in Metro Style

    Question

  • According to msdn documentation, several synchronization function like WaitForSingleObjectEx, CreateEventExW, ResetEvent, SetEvent is supported in metro style apps.In CreateEventExW() function now allowed to define access right through its fourth parameter.

    WaitForSingleObjectEx() needs SYNCHRONIZE access rights while ResetEvent/SetEvent  function needs EVENT_MODIFY_STATE access rights.

    So, How we can use this two function for the same event simultaneously??? Is it bug ?

    Can I use this synchronization function to synchronize PPLTASK/Asynchronous Procedure Call in metro ? If not how we can block an asynchronous operation (if required) in metro style app??

    Here is my pseudo code scenario in WinRT:

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

    ResetEvent(htest);

    task<void>(stmsocket->ConnectAsync(remoteHostName, remoteServiceName, SocketProtectionLevel::PlainSocket)).then([this] (task<void> previousTask) {
            try{     SetEvent(htest); //Success   }

    catch(Exception e) {       SetEvent(htest); //Failure    }

    DWORD dwRet = WaitForSingleObjectEx(htest, INFINITE, TRUE);

    In this case WaitForSingleObjectEx() wait for ever. Why??? Is WaitForSingleObjectEx usable for APC ?

    Thursday, August 02, 2012 4:36 AM

Answers

  • Note, calling Wait on a UI thread blocks it. this is not allowed in windows 8 store apps, and equally bad (but allowed) in desktop apps.

    one way to think about this, instead of adding code that signals an event when the completion handler is called put the code you want to run there instead.

    also, I recommend using ppl create_task(), here is a code fragment from the sample

            create_task(CredentialPicker::PickAsync(Message->Text, Target->Text)) 
                .then([this](CredentialPickerResults^ credPickerResult) 
            { 
                auto domainName = credPickerResult->CredentialDomainName; 
                auto userName = credPickerResult->CredentialUserName; 
                auto password = credPickerResult->CredentialPassword; 
                auto savedByApi = credPickerResult->CredentialSaved; 
                auto saveOption = credPickerResult->CredentialSaveOption; 
                // process the results here
            }); 

    Monday, September 03, 2012 9:19 PM
  • Above problem is resolved.

    In UI thread, synchronization is not possible by blocking, because UI thread does not allow any blocking. Task chain can be used for sequential operation.

    task chains, -> myTask.then(…).then(…).then(…);

    In a separate worker thread can be synchronized by following.

    task<void>( ConnectAsync( ... )  ).then([this] (task<void> previousTask) {
            try{ 
        previousTask.get();
        SetEvent(htest); //Success   
    }
    catch(Exception e) {    
       SetEvent(htest); //Failure 
       }
    
    WaitForSingleObjectEx(htest, INFINITE, TRUE);

    Monday, September 24, 2012 6:10 PM

All replies

  • It is inadvisable to block the UI thread in this manner.  Continuations scheduled off an async operation via a call to .then will by default be scheduled to run back on the UI thread.  What's probably happening here is that the main thread is blocked waiting for htest to be signaled while your call to ConnectAsync is still running asynchronously.  When the asynchronous call finishes, the continuation in which you do your SetEvent call is scheduled to run on the UI thread.  Since the UI thread is blocked waiting on htest, that continuation cannot run and the thread deadlocks.

    Is there a reason you are waiting synchronously in the UI thread for this operation to complete.  Can you not perform the operation itself in the continuation off ConnectAsync...?

    Thursday, August 02, 2012 3:26 PM
  • We have a similar problem to the one described above. Basically we want to use the use the CredentialPicker to obtain some credentials , sign in with those credentials, and then proceeed with the flow. We want to block on the UI thread until the user enters the credentials (or cancels). The Completed code , however, never gets called. Any suggestions?

    Note that a similar construct in C# works fine(see code below)

    C++ code:

    HANDLE hEvent = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS );

      try
      {
       auto credResult = CredentialPicker::PickAsync("test","test");
       credResult->Completed = ref new AsyncOperationCompletedHandler<CredentialPickerResults^>([hEvent, userName, userPassword](IAsyncOperation<CredentialPickerResults^>^ operation, AsyncStatus aaa)
       {
        auto res= operation->GetResults();
        auto saveOption = res->CredentialSaveOption;
        auto userName = res->CredentialUserName;
        auto password = res->CredentialPassword;

        //TODO - Sign in with the obtained credentials

        SetEvent(hEvent);
       });
      }catch(Exception^ ex)
      {
       SetEvent(hEvent);
      }

     DWORD dwWaitResult = WaitForSingleObjectEx(hEvent, INFINITE, true);

     //TODO - continue the execution flow

    C# code:

                ManualResetEvent m = new ManualResetEvent(false);
                await CurrentDispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(async () =>
                {
                    CredentialPickerOptions credPickerOptions = new CredentialPickerOptions();
                    credPickerOptions.TargetName = "Target";
                    credPickerOptions.Message = "Message";
                    credPickerOptions.AlwaysDisplayDialog = true;
                    credPickerOptions.CallerSavesCredential = true;
                    credPickerOptions.CredentialSaveOption = CredentialSaveOption.Selected;
                    credPickerOptions.AuthenticationProtocol = AuthenticationProtocol.Basic;

                    var action = CredentialPicker.PickAsync(credPickerOptions);
                    action.Completed = new AsyncOperationCompletedHandler<CredentialPickerResults>(async (IAsyncOperation<CredentialPickerResults> source, AsyncStatus status) =>
                    {
                        var results = action.GetResults();

                        userName = results.CredentialUserName;
                        userPassword = results.CredentialPassword;
                        saveCredentialsFlag = (results.CredentialSaveOption == CredentialSaveOption.Selected);
                        //TODO SignIn
                        m.Set();
                    });
                }));

                m.WaitOne();

               //TODO - continue flow


    • Edited by Pete Edberg Friday, August 03, 2012 12:42 AM
    Friday, August 03, 2012 12:40 AM
  • Thanks for your reply.

    "Is there a reason you are waiting synchronously in the UI thread for this operation to complete."

    Yes!

    "Can you not perform the operation itself in the continuation off ConnectAsync...?"

    No!

    We have a Win32 project and we would like to port it in metro. Our project is built on synchronous model and we are not interested to rewrite it. As WinRT is asynchronous and our system expect synchronous behaviour, we would like to write a synchronous wrapper for some native function of WinRT (e.g. networking.socket namespace). That's why, I am trying to make synchronous some asynchronous methods.

    By the way, Could you tell me about Multithreading in WinRT ? How could I create a new worker thread under MTA in metro style app? I think Windows.System.Threading is not sufficient and it also asynchronous. Any others details resource about WinRT thread.

    Monday, August 06, 2012 10:37 AM
  • I haven't caught the "async" religion and don't like all the async stuff in the samples. However, it looks like you can simply use _beginthreadex() and a normal Win32 thread to do your background synchronous processing in Metro/WinRT/whatever it's called now. That's what I'm going to do in my Metro app. I compiled a _beginthreadex() test app and it passed the certification check so I assume a full submission to the store would pass as well.

    *Note: I haven't looked at the C++ runtime source so I don't know what _beginthreadex is actually doing. It may use some sort of worker threading scheme or simply the CreateThread API.

    Monday, August 06, 2012 4:06 PM
  • I compiled a _beginthreadex() test app and it passed the certification check so I assume a full submission to the store would pass as well.

    http://msdn.microsoft.com/en-us/library/hh674596.aspx - _beginthreadex and _beginthread "cannot be used in Windows Metro style apps that execute in the Windows Runtime"
    Tuesday, August 21, 2012 9:50 AM
  • I compiled a _beginthreadex() test app and it passed the certification check so I assume a full submission to the store would pass as well.

    http://msdn.microsoft.com/en-us/library/hh674596.aspx - _beginthreadex and _beginthread "cannot be used in Windows Metro style apps that execute in the Windows Runtime"
    Yep, that's a change in the RTM version of VS2012. Now I'm stuck wading through the goofy async stuff. Hard to believe MSFT threw away 20 years worth of battle-tested multithreading code (it's still there in the core, just unavailable).
    Tuesday, August 21, 2012 8:41 PM
  • i'm having the same problem myself.  frustrating.  any pointers on how to go about creating custom C++ async calls for WinRT?  Do you have to use the AsyncBase?
    Monday, September 03, 2012 3:19 PM
  • time to start learning how the async system works ;-)\

    Apps that hang the UI thread are not appreciated by end users.

    Start by studying the SDK samples demonstrate how to use the APIs you are using. Once you learn a few of the concepts you will have success.

    here is where to start: http://msdn.microsoft.com/en-us/library/windows/apps/Hh780559.aspx

    and here is the credential picker sample, you can browse the code directly from this page

    http://code.msdn.microsoft.com/windowsapps/Credential-picker-sample-30fcba2e

    • Edited by Chris Guzak Monday, September 03, 2012 9:14 PM
    Monday, September 03, 2012 9:13 PM
  • Note, calling Wait on a UI thread blocks it. this is not allowed in windows 8 store apps, and equally bad (but allowed) in desktop apps.

    one way to think about this, instead of adding code that signals an event when the completion handler is called put the code you want to run there instead.

    also, I recommend using ppl create_task(), here is a code fragment from the sample

            create_task(CredentialPicker::PickAsync(Message->Text, Target->Text)) 
                .then([this](CredentialPickerResults^ credPickerResult) 
            { 
                auto domainName = credPickerResult->CredentialDomainName; 
                auto userName = credPickerResult->CredentialUserName; 
                auto password = credPickerResult->CredentialPassword; 
                auto savedByApi = credPickerResult->CredentialSaved; 
                auto saveOption = credPickerResult->CredentialSaveOption; 
                // process the results here
            }); 

    Monday, September 03, 2012 9:19 PM
  • Above problem is resolved.

    In UI thread, synchronization is not possible by blocking, because UI thread does not allow any blocking. Task chain can be used for sequential operation.

    task chains, -> myTask.then(…).then(…).then(…);

    In a separate worker thread can be synchronized by following.

    task<void>( ConnectAsync( ... )  ).then([this] (task<void> previousTask) {
            try{ 
        previousTask.get();
        SetEvent(htest); //Success   
    }
    catch(Exception e) {    
       SetEvent(htest); //Failure 
       }
    
    WaitForSingleObjectEx(htest, INFINITE, TRUE);

    Monday, September 24, 2012 6:10 PM