locked
BackgroundDownloader in c++

    Question

  • Hi,

    Trying to run a simple file loader, but code crashes at downloadTask.wait( );  Could you help - what is wrong with it?

        Windows::Storage::StorageFolder^ folder = ApplicationData::Current->RoamingFolder;

        String^ file_name = "index.html";

        auto create_file_op = folder->CreateFileAsync( file_name );

        task< StorageFile^ > createFileTask( create_file_op );

        createFileTask.then( [ this ] ( StorageFile^ file )
        {

              BackgroundDownloader^  bd = ref new BackgroundDownloader( );

              DownloadOperation^ loader_op = bd->CreateDownload( ref new Uri("http://www.google.com/index.html"), file );

              task< DownloadOperation^ > downloadTask( loader_op->StartAsync( ) );

              downloadTask.wait( ); 

        } );

    Internet capabilities are set.


    • Edited by Vladbph Tuesday, April 03, 2012 4:35 AM
    Monday, April 02, 2012 10:24 PM

Answers

  • Here's the C# 'BackgroundTransferDownload' sample coverted to C++/CX:

    	Windows::Storage::StorageFolder^ folder = ApplicationData::Current->RoamingFolder;
    	String^ file_name = "index.html";
     
    	// http://blogs.msdn.com/b/nativeconcurrency/archive/2011/10/27/try-it-now-use-ppl-to-produce-windows-8-asynchronous-operations.aspx
    
    	task<StorageFile^>(folder->CreateFileAsync(file_name, CreationCollisionOption::ReplaceExisting))
    		.then([&](StorageFile^ file)
    	{
    		wchar_t msgbuffer[1024] = {0};
    		_swprintf(msgbuffer, L"Created %s\n", file->Name->Data());
    		::OutputDebugString(msgbuffer);
    
    		BackgroundDownloader^  bd = ref new BackgroundDownloader( );
    		DownloadOperation^ loader_op = bd->CreateDownload( ref new Uri("http://www.google.com/index.html"), file );
    		
    		task<DownloadOperation^>(loader_op->StartAsync())
    			.then([&](DownloadOperation^ opCallback) -> DownloadOperation^
    		{
    			wchar_t msgbuffer[1024] = {0};
    			swprintf(msgbuffer, L"Progress: %s, Status: %d\n", 
    				StringFromGuid(opCallback->Guid)->Data(), opCallback->Progress.Status);
    			::OutputDebugString(msgbuffer);
    
    			if (opCallback->Progress.TotalBytesToReceive > 0)
                {
                    long long percent = opCallback->Progress.BytesReceived * 100 
    										/ opCallback->Progress.TotalBytesToReceive;
    				swprintf(msgbuffer, L" - Transfered bytes: %I64d of %I64d - %I64d%%\n", 
    					opCallback->Progress.BytesReceived, opCallback->Progress.TotalBytesToReceive, percent);
    				::OutputDebugString(msgbuffer);
                }
    			else
                {
    				swprintf(msgbuffer, L" - Transfered bytes: %d\n", opCallback->Progress.BytesReceived);
    				::OutputDebugString(msgbuffer);
                }
    
                if (opCallback->Progress.HasRestarted)
                {
    				::OutputDebugString(L" - Download restarted\n");
                }
    
                if (opCallback->Progress.HasResponseChanged)
                {
                    // We've received new response headers from the server.
    				swprintf(msgbuffer, L" - Response updated; Header count: %d\n", 
    							opCallback->GetResponseInformation()->Headers->Size);
    				::OutputDebugString(msgbuffer);
                }
    
    			return opCallback;
    		}).then([&](DownloadOperation^ opResponse)
    			{
    				wchar_t msgbuffer[1024] = {0};
    				ResponseInformation^ response = opResponse->GetResponseInformation();
    				swprintf(msgbuffer, L"Completed: %s, Status Code: %d\n", 
    					StringFromGuid(opResponse->Guid)->Data(), response->StatusCode);
    				::OutputDebugString(msgbuffer);
    			});
    	});

    And the debugger output

    Progress: {8235A730-26FC-47F7-9118-CB88AA93BE7C}, Status: 5
     - Transfered bytes: 93618 of 93618 - 100%
     - Response updated; Header count: 11
    Completed: {8235A730-26FC-47F7-9118-CB88AA93BE7C}, Status Code: 200
    -Steve
    Tuesday, April 03, 2012 10:09 PM
    Moderator

All replies

  • How about try-catch block.

    NEU_ShieldEdge

    Tuesday, April 03, 2012 5:49 AM
  • I removed it to show simplified code. try-catch doesn't catch. There are examples of the class use in VB and C#, but none on c++ and apparently there is a difference.

    Here is the debugger output:

    First-chance exception at 0x754456C4 in StreamSocket.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000.
    First-chance exception at 0x754456C4 in StreamSocket.exe: Microsoft C++ exception: Concurrency::invalid_operation at memory location 0x02F6CCD0.
    First-chance exception at 0x754456C4 in StreamSocket.exe: Microsoft C++ exception: Concurrency::invalid_operation at memory location 0x02F6DA6C.
    First-chance exception at 0x754456C4 in StreamSocket.exe: Microsoft C++ exception: Concurrency::unobserved_task_exception at memory location 0x02F6C228.
    Debug Error!
    Program: ...eamSocket sample\C++\Debug\StreamSocket\AppX\StreamSocket.exe
    R6010
    - abort() has been called

    • Edited by Vladbph Tuesday, April 03, 2012 5:30 PM
    Tuesday, April 03, 2012 3:12 PM
  • Here's the C# 'BackgroundTransferDownload' sample coverted to C++/CX:

    	Windows::Storage::StorageFolder^ folder = ApplicationData::Current->RoamingFolder;
    	String^ file_name = "index.html";
     
    	// http://blogs.msdn.com/b/nativeconcurrency/archive/2011/10/27/try-it-now-use-ppl-to-produce-windows-8-asynchronous-operations.aspx
    
    	task<StorageFile^>(folder->CreateFileAsync(file_name, CreationCollisionOption::ReplaceExisting))
    		.then([&](StorageFile^ file)
    	{
    		wchar_t msgbuffer[1024] = {0};
    		_swprintf(msgbuffer, L"Created %s\n", file->Name->Data());
    		::OutputDebugString(msgbuffer);
    
    		BackgroundDownloader^  bd = ref new BackgroundDownloader( );
    		DownloadOperation^ loader_op = bd->CreateDownload( ref new Uri("http://www.google.com/index.html"), file );
    		
    		task<DownloadOperation^>(loader_op->StartAsync())
    			.then([&](DownloadOperation^ opCallback) -> DownloadOperation^
    		{
    			wchar_t msgbuffer[1024] = {0};
    			swprintf(msgbuffer, L"Progress: %s, Status: %d\n", 
    				StringFromGuid(opCallback->Guid)->Data(), opCallback->Progress.Status);
    			::OutputDebugString(msgbuffer);
    
    			if (opCallback->Progress.TotalBytesToReceive > 0)
                {
                    long long percent = opCallback->Progress.BytesReceived * 100 
    										/ opCallback->Progress.TotalBytesToReceive;
    				swprintf(msgbuffer, L" - Transfered bytes: %I64d of %I64d - %I64d%%\n", 
    					opCallback->Progress.BytesReceived, opCallback->Progress.TotalBytesToReceive, percent);
    				::OutputDebugString(msgbuffer);
                }
    			else
                {
    				swprintf(msgbuffer, L" - Transfered bytes: %d\n", opCallback->Progress.BytesReceived);
    				::OutputDebugString(msgbuffer);
                }
    
                if (opCallback->Progress.HasRestarted)
                {
    				::OutputDebugString(L" - Download restarted\n");
                }
    
                if (opCallback->Progress.HasResponseChanged)
                {
                    // We've received new response headers from the server.
    				swprintf(msgbuffer, L" - Response updated; Header count: %d\n", 
    							opCallback->GetResponseInformation()->Headers->Size);
    				::OutputDebugString(msgbuffer);
                }
    
    			return opCallback;
    		}).then([&](DownloadOperation^ opResponse)
    			{
    				wchar_t msgbuffer[1024] = {0};
    				ResponseInformation^ response = opResponse->GetResponseInformation();
    				swprintf(msgbuffer, L"Completed: %s, Status Code: %d\n", 
    					StringFromGuid(opResponse->Guid)->Data(), response->StatusCode);
    				::OutputDebugString(msgbuffer);
    			});
    	});

    And the debugger output

    Progress: {8235A730-26FC-47F7-9118-CB88AA93BE7C}, Status: 5
     - Transfered bytes: 93618 of 93618 - 100%
     - Response updated; Header count: 11
    Completed: {8235A730-26FC-47F7-9118-CB88AA93BE7C}, Status Code: 200
    -Steve
    Tuesday, April 03, 2012 10:09 PM
    Moderator
  • And the helper function StringFromGuid

    Platform::String^ StringFromGuid(GUID guid)
    {
    	const int bufflen = 40;
    	wchar_t guidbuffer[bufflen] = {0};
    	::StringFromGUID2(guid, guidbuffer, bufflen);
    	return ref new Platform::String(guidbuffer);
    }

    Tuesday, April 03, 2012 10:10 PM
    Moderator
  • Thank you very much!
    Tuesday, April 03, 2012 11:36 PM