locked
Are All Windows Runtime Classes and their APIs multithread-safe?

    Question


  • Hi, I'm developing an Windows Store App which needs multi-threaded handling by c++/cx.

    I'm using std::thread class to open thread, and I wish to implement a log function by StorageFile class for all threads to write to the same log file.

    But I found StorageFile::GetBasicPropertiesAsync() API get stuck if I don't use mutex to protect the StorageFile object.

    Here is my code:

    #include <thread>
    
    ref class FileChainer
    {
    internal:
        StorageFile^ file;    
        FileChainer() : file(nullptr)
        {}
    };
    
    static void File_Stat();
    
    void StatTest()
    {
        //open 10 thread to GetBasicPropertiesAsync()
        for(int i=0 ; i<10 ; i++) {
            std::thread statTh(File_Stat);
            statTh.detach();
        }
    }
    
    void File_Stat()
    {
        while(true) {
            FileChainer^ chainer = ref new FileChainer();
    
            //get StorageFile reference
            HANDLE get_event = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
            auto getOP = ApplicationData::Current->LocalFolder->GetFileAsync("test.log");
            getOP->Completed = ref new AsyncOperationCompletedHandler<StorageFile^> (
                [&get_event,chainer] (IAsyncOperation<StorageFile^>^ op, AsyncStatus status) {
                    try {
                        chainer->file = op->GetResults();
                    }
                    catch (Exception^ ex) {
                        String^ msg = "GetFileAsync failed: "+ex->Message+"\n";
                        OutputDebugStringW(msg->Data());
                    }
                    SetEvent(get_event);
                }
            );
            WaitForSingleObjectEx(get_event, INFINITE, TRUE);
            CloseHandle(get_event);
    
            if(chainer->file == nullptr) {
                String^ msg = "GetFile failed!\n";
                OutputDebugStringW(msg->Data());
                continue;
            }
    
            //get property
            int64_t fileSize = -1;
            HANDLE getprop_event = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
            auto getPropsAction = chainer->file->GetBasicPropertiesAsync();
            getPropsAction->Completed = ref new AsyncOperationCompletedHandler<BasicProperties^> (
                [&getprop_event,&fileSize] (IAsyncOperation<BasicProperties^>^ op, AsyncStatus status) {
                    try {
                        auto props = op->GetResults();
                        fileSize = props->Size;
                    }
                    catch (Exception^ ex) {
                        String^ msg = "GetBasicPropertiesAsync failed: "+ex->Message+"\n";
                        OutputDebugStringW(msg->Data());
                    }
                    SetEvent(getprop_event);
            });
            WaitForSingleObjectEx(getprop_event, INFINITE, TRUE);
            CloseHandle(getprop_event);
            
            if(fileSize>=0){
                String^ msg = "Stat file success, size="+fileSize.ToString()+".\n";
                OutputDebugStringW(msg->Data());
            }
            
            delete chainer;
            std::this_thread::sleep_for(std::chrono::millseconds(1));
        }
    }
    After long run about 3~5 hours, some threads stuck at 
    auto getPropsAction = chainer->file->GetBasicPropertiesAsync();
    and never return.

    Here is StorageFile::GetBasicPropertiesAsync() MSDN document:

    http://msdn.microsoft.com/library/windows/apps/Hh701737

    From this document, I can't find any description about multithreaded-safe of this API.


    There is also a document talk about multithreaded environment:

    http://msdn.microsoft.com/en-us/library/windows/apps/jj157115.aspx

    It says:

    In both the Windows Runtime and the .NET Framework, most classes are not thread safe because thread safety has a performance cost, and most objects are never accessed by multiple threads. It's more efficient to synchronize access to individual objects (or to use thread-safe classes) only as necessary.


    My question are:

    1. Are all Windows Runtime classes and their APIs multithread-safe?

    2. If partial yes for #1, is there any document talking about which Windows Runtime APIs are multithread-safe?

    3. Is there any Windows Runtime API that can act like Win32 API to share-write for a single file in different threads (need NO mutex to protect the file handle)?

    Thanks.

    Friday, February 22, 2013 7:46 AM

Answers

  • 1. No. As noted in the documentation you quote, most classes are not thread safe.

    2. There is no centralized document. Individual classes which are thread safe should say so in their documentation. Classes which aren't documented as thread safe should be assumed not to be.

    3. If the files you are looking at are in your app data directory then the app can access them directly with standard C functions such as fopen or Win32 functions such as CreateFile2.

    --Rob

    • Proposed as answer by Jesse Jiang Monday, February 25, 2013 2:49 AM
    • Marked as answer by truckwu Tuesday, February 26, 2013 3:44 AM
    Saturday, February 23, 2013 2:06 AM
    Owner

All replies

  • 1. No. As noted in the documentation you quote, most classes are not thread safe.

    2. There is no centralized document. Individual classes which are thread safe should say so in their documentation. Classes which aren't documented as thread safe should be assumed not to be.

    3. If the files you are looking at are in your app data directory then the app can access them directly with standard C functions such as fopen or Win32 functions such as CreateFile2.

    --Rob

    • Proposed as answer by Jesse Jiang Monday, February 25, 2013 2:49 AM
    • Marked as answer by truckwu Tuesday, February 26, 2013 3:44 AM
    Saturday, February 23, 2013 2:06 AM
    Owner
  • Hi Rob,

    Thanks for you reply, it really helps me to identify the ideas.

    About #3 If the files you are looking at are in your app data directory then the app can access them directly with standard C functions such as fopen or Win32 functions such as CreateFile2.

    I remember in MSFT official reply and Win8 conferences, Microsoft strongly recommend WOA developers NOT to use Win32 API, And That is the reason I choose to find an pure Windows Runtime solution to do shared write behavior.

    So my further question will be: If I use Win32 APIs which are supported on Windows Store APP for ARM platform, will them impact the review of my APP for publish?

    Tuesday, February 26, 2013 3:11 AM
  • So my further question will be: If I use Win32 APIs which are supported on Windows Store APP for ARM platform, will them impact the review of my APP for publish?


    It should not impact the review, no. The Windows 8 App Certification Requirements ( http://msdn.microsoft.com/en-us/library/windows/apps/hh694083.aspx ) make clear (see ACR 3.1) that your app must only use the Windows Runtime APIs. It goes on to provide a link to the approved APIs, http://msdn.microsoft.com/en-us/library/windows/apps/br211369.aspx , which includes the Win32 and COM APIs that you can use. To the best of my knowledge, you can also use all C++ Standard Library functionality with Windows Store apps as well. You can confirm whether or not your app is making use of disallowed APIs by running it through the Windows App Cert Kit (WACK) utility, which is provided with the Windows 8 SDK. For more about WACK, see this link: http://msdn.microsoft.com/en-us/library/windows/apps/hh694081.aspx .

    XNA/DirectX MVP | Website | Blog | @mikebmcl

    Tuesday, February 26, 2013 3:40 AM
  • The same API are available to Windows Store apps on Windows 8 and on Windows RT. Any Win32 or C-runtime API which are allowed for Windows Store apps on Windows 8 are also allowed on Windows RT.

    --Rob

    Tuesday, February 26, 2013 4:25 AM
    Owner