locked
why can't I write a file write code like this?

    Question

  • I want to create a log file and write some text in. I want to make sure the text been written to file and then go to next step.

    So I add "task.get()" to make sure the AppendTextAsync to finish. However, if this code exist my code will always failed with exception which can not be seen in Visual studio. I want to someone help to explain, why code like this will cause exception and the correct way for this:

      

    create_task(KnownFolders::DocumentsLibrary->CreateFileAsync("log.txt", CreationCollisionOption::ReplaceExisting)).then([this](StorageFile^ file) { task<void> task = create_task(Windows::Storage::FileIO::AppendTextAsync(file, "hello")); task.get();

    ... //do other thing

    });


    • Edited by XXXing Tuesday, June 25, 2013 10:47 AM
    Tuesday, June 25, 2013 10:43 AM

Answers

  • The only use that I can see for task.get() in this place is to capture exceptions in the try block.  It does not have a role in assuring the async operation is complete.  That is the function of the .then clause.

    Sorry, I can't answer the second part of your question.  The different ways the async pattern is used in the various examples I have seen are confusing to me.  Some use create_task, others do not.  Some use create_task on an outer block and not on the inner one.  Some use task<T> as the argument in the lambda and others just the naked variable.

    Tuesday, June 25, 2013 11:56 AM

All replies

  • I think there are a couple of problems with this code.

    1. need to use .then construct to wait for task to complete
    2. the CreationCollisionOption chosen will delete the old log file every time it is called.  You want it to be appended to.

    Look at this example:

    	auto localFolder =  ApplicationData::Current->LocalFolder;
    	create_task(localFolder->CreateFileAsync("dataFile.txt", CreationCollisionOption::OpenIfExists)).then([this](StorageFile^ sampleFile)
    	{
    		auto calendar = ref new Calendar;
    		calendar->SetToNow();
    		auto now = calendar->GetDateTime();
    		auto formatter = ref new Windows::Globalization::DateTimeFormatting::DateTimeFormatter("longtime");
    		auto logString = (formatter->Format(now)) + L"\n";
    		create_task(FileIO::AppendTextAsync(sampleFile, logString)).then([this]()
    		{
    			try {
    				LocalTextOut->Text = "TimeStamp Saved to dataFile.txt in Local";
    			} catch (Exception^ e) {
    				LocalTextOut->Text = e->ToString();
    			}
    		});
    	});

    Tuesday, June 25, 2013 11:11 AM
  • Thanks, jrboddie

    I got several follow up questions,

    1. I got code from file access sample :

                create_task(FileIO::WriteBufferAsync(file, buffer)).then([this, file, buffer, userContent](task<void> task)
                {
                    try
                    {
                        task.get();
                        OutputTextBlock->Text = "The following " + buffer->Length.ToString() + " bytes of text were written to '" + file->Name + "':\n\n" + userContent;
                    }
                    catch(COMException^ ex)
                    {
                        rootPage->HandleFileNotFoundException(ex);
                    }
                });
    

    if .then can make sure the async task is complete, does that means calling "task.get()" is not necessary here?

    And my second question is about the WriteBufferAsync task, because it is always a async operation, how can I make sure the text being written is FIFO sequence? And in my code , I have a logMessage() function inturn calling AppendTextAsync to write text, I do discover some of writing text operation not write the text in, some text lost, can you give some suggestion about this?

    Tuesday, June 25, 2013 11:38 AM
  • The only use that I can see for task.get() in this place is to capture exceptions in the try block.  It does not have a role in assuring the async operation is complete.  That is the function of the .then clause.

    Sorry, I can't answer the second part of your question.  The different ways the async pattern is used in the various examples I have seen are confusing to me.  Some use create_task, others do not.  Some use create_task on an outer block and not on the inner one.  Some use task<T> as the argument in the lambda and others just the naked variable.

    Tuesday, June 25, 2013 11:56 AM