locked
Win8 Bluetooth to device issue: how to invoke DataReader's LoadAsync() repeatedly in a separate data receive thread ?

    Question

  • the code below:

    task<String^> CBTWinRTDLL::RecvDataAsync()
    {
    	if (!CoreApplication::Properties->HasKey("clientSocket"))
    	{
    		auto op = create_async([]()
    		{
    		});
    
    		return create_task(op).then([]()
    		{
    			String^ retStr = "Client socket does not exist, please connect device first.";
    			return retStr;
    		});
    	}
    
    	_reader->InputStreamOptions = InputStreamOptions::Partial;
    
    	task<unsigned int> ReadTask(_reader->LoadAsync(256));
    	return ReadTask.then([this](task<unsigned int> readTask)
    	{
    		try
    		{
    			int readSize = readTask.get();
    
    			Platform::String^ recvStr;
    			if ((readSize) > 0)
    			{
    				Platform::Array<unsigned char>^ recvArr = ref new Platform::Array<unsigned char, 1>(readSize);
    				_reader->ReadBytes(recvArr);
    				std::string strHex = toString(recvArr->Data, recvArr->Length);
    				recvStr = stops(strHex);
    			}
    			else
    			{
    				recvStr = "";
    			}
    			return recvStr;
    		}
    		catch (Exception^ ex)
    		{
    			return ex->Message;
    		}
    	});
    }

    The RecvDataAsync() is a method within WinRT DLL and  will be invoked from a metro app,  it can receive data if there are some data in the socket's inputstream after socket connected.  But if BT device doesn't send data , invoke this method will cause a exception at this line:   task<unsigned int> ReadTask(_reader->LoadAsync(256));

    My question is:  how to create a separately thread or task to keep monitorring the StreamSocket's inputstream(or any other)  after  bluetooth device is connected or socket->ConnectAsync() is succeeded ?  

    what I need is a WinRT DLL method like my code snippet,  it can running asynchronous in workerthread , detect Tcp stream , if there were data sent from BT device , then receive  and  forward to metro app,  otherwize, it should just loopping until user click the stop button in metro app or socket been closed.


    nio


    • Edited by nio Pan Thursday, December 26, 2013 6:01 AM
    Thursday, December 26, 2013 4:35 AM

Answers

  • Hi nio Pan,

    Here is no event for this, you just need to build a loop to check if there is something that you are interested in.

    What's your error info? Would you mind sharing it with me?

    And also you could have a try on the follow code, maybe it is helpful:

    void ListenerContext::ReceiveStringLoop(DataReader^ reader, StreamSocket^ socket)
    {
        // Read first 4 bytes (length of the subsequent string).
        task<unsigned int>(reader->LoadAsync(sizeof(UINT32))).then([this, reader, socket] (unsigned int size)
        {
            if (size < sizeof(UINT32))
            {
                // The underlying socket was closed before we were able to read the whole data.
                cancel_current_task();
            }
    
            unsigned int stringLength = reader->ReadUInt32();
            return task<unsigned int>(reader->LoadAsync(stringLength)).then([this, reader, stringLength] (unsigned int actualStringLength)
            {
                if (actualStringLength != stringLength)
                {
                    // The underlying socket was closed before we were able to read the whole data.
                    cancel_current_task();
                }
                
                // Display the string on the screen. This thread is invoked on non-UI thread, so we need to marshal the call back to the UI thread.
                NotifyUserFromAsyncThread("Received data: \"" + reader->ReadString(actualStringLength) + "\"", NotifyType::StatusMessage);
            });
        }).then([this, reader, socket] (task<void> previousTask)
        {
            try
            {
                // Try getting all exceptions from the continuation chain above this point.
                previousTask.get();
    
                // Everything went ok, so try to receive another string. The receive will continue until the stream is broken (i.e. peer closed closed the socket).
                ReceiveStringLoop(reader, socket);
            }
            catch (Exception^ exception)
            {
                NotifyUserFromAsyncThread("Read stream failed with error: " + exception->Message, NotifyType::ErrorMessage);
    
                // Explicitly close the socket.
                delete socket;
            }
            catch (task_canceled&)
            {
                // Do not print anything here - this will usually happen because user closed the client socket.
    
                // Explicitly close the socket.
                delete socket;
            }
        });
    }

    Regards!

    Xiaoliang


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, December 30, 2013 7:13 AM
    Moderator

All replies

  • question 2:  or are there any event for data arriving from bluetooth device by using stream socket , so i can LoadAsync() data and readBytes() in the event handler?   Because i don't know when the data will incomming,  if BT device doesn't send data  and i LoadAsync(),  the exception will raise.

    nio


    • Edited by nio Pan Thursday, December 26, 2013 6:58 AM
    Thursday, December 26, 2013 6:57 AM
  • Hi nio Pan,

    Here is no event for this, you just need to build a loop to check if there is something that you are interested in.

    What's your error info? Would you mind sharing it with me?

    And also you could have a try on the follow code, maybe it is helpful:

    void ListenerContext::ReceiveStringLoop(DataReader^ reader, StreamSocket^ socket)
    {
        // Read first 4 bytes (length of the subsequent string).
        task<unsigned int>(reader->LoadAsync(sizeof(UINT32))).then([this, reader, socket] (unsigned int size)
        {
            if (size < sizeof(UINT32))
            {
                // The underlying socket was closed before we were able to read the whole data.
                cancel_current_task();
            }
    
            unsigned int stringLength = reader->ReadUInt32();
            return task<unsigned int>(reader->LoadAsync(stringLength)).then([this, reader, stringLength] (unsigned int actualStringLength)
            {
                if (actualStringLength != stringLength)
                {
                    // The underlying socket was closed before we were able to read the whole data.
                    cancel_current_task();
                }
                
                // Display the string on the screen. This thread is invoked on non-UI thread, so we need to marshal the call back to the UI thread.
                NotifyUserFromAsyncThread("Received data: \"" + reader->ReadString(actualStringLength) + "\"", NotifyType::StatusMessage);
            });
        }).then([this, reader, socket] (task<void> previousTask)
        {
            try
            {
                // Try getting all exceptions from the continuation chain above this point.
                previousTask.get();
    
                // Everything went ok, so try to receive another string. The receive will continue until the stream is broken (i.e. peer closed closed the socket).
                ReceiveStringLoop(reader, socket);
            }
            catch (Exception^ exception)
            {
                NotifyUserFromAsyncThread("Read stream failed with error: " + exception->Message, NotifyType::ErrorMessage);
    
                // Explicitly close the socket.
                delete socket;
            }
            catch (task_canceled&)
            {
                // Do not print anything here - this will usually happen because user closed the client socket.
    
                // Explicitly close the socket.
                delete socket;
            }
        });
    }

    Regards!

    Xiaoliang


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, December 30, 2013 7:13 AM
    Moderator