2

im trying to Reading/Writing Async Files for an Universal App in c#. When i write and read a file for first time, it works... But when i retry it immeadiatly, there are two Errors: 1. UnauthorizedAccess 2. Handle with the OPLOCK has been closed

It seems that the methods arent finished yet and so the data is not free

(in my frame is a button which adds a new member to a List, then the list shall serialized in an XML data. When i reNavigate to that page, that XML sheet shall be deserialized back to that List, because the Content shall be displayed)

List<Immobilie> immoListe = new List<Immobilie>();
private const string FileName_ImmoObjects = "ImmoObjects.xml";
StorageFolder sFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
IStorageFile latestImmoListFile;

 public Startmenue()
    {
        this.InitializeComponent();
        immoListe.Add(new Immobilie()); // for testing creating an XML first
        immoListe[0].adresse = "Foo1";  
        immoListe.Add(new Immobilie());
        immoListe[1].adresse = "Foo2";
        WriteImmoListAsync();   
        ReadImmoListAsync();   // These two steps working

        WriteImmoListAsync(); // everything more causes error  
        ReadImmoListAsync();   

    }

public async void WriteImmoListAsync()
    {
        try
        {
            IStorageFolder folder = await sFolder.CreateFolderAsync("Saves", CreationCollisionOption.OpenIfExists);
            latestImmoListFile = await folder.CreateFileAsync(FileName_ImmoObjects, CreationCollisionOption.ReplaceExisting);

            using (IRandomAccessStream stream = await latestImmoListFile.OpenAsync(FileAccessMode.ReadWrite))
            using (Stream outputStream = stream.AsStreamForWrite())
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(List<Immobilie>));
                serializer.WriteObject(outputStream, immoListe);
            }

        }
        catch (Exception e)
        {
            var d = new MessageDialog(e.ToString());
            await d.ShowAsync();
        }
    }



    public async void ReadImmoListAsync()
    {
        int i = 0;
        try
        {
            IStorageFolder folder = await sFolder.GetFolderAsync("Saves");
            i = 1;
            latestImmoListFile = await folder.GetFileAsync(FileName_ImmoObjects);
            i = 2;
            using (IRandomAccessStream stream = await latestImmoListFile.OpenAsync(FileAccessMode.Read))
            {
                i = 3;
                using (Stream inputStream = stream.AsStreamForRead())
                {
                    i = 4;
                    DataContractSerializer deserializer = new DataContractSerializer(typeof(List<Immobilie>));
                    i = 5;
                    immoListe = (List<Immobilie>)deserializer.ReadObject(inputStream);
                }
            }

        }
        catch (Exception e)
        {
            var d = new MessageDialog("Fehler I = " + i + "\n" + e.ToString());
            await d.ShowAsync();
        }
    }

So what can i do and why is it so difficult??(normal I/O is easy-peasy).-.

Clemens
  • 123,504
  • 12
  • 155
  • 268
3009Robin
  • 21
  • 3

3 Answers3

2

As I describe in my MSDN article on async best practices, you should avoid async void:

public async Task WriteImmoListAsync();
public async Task ReadImmoListAsync();

Once your methods are properly async Task, then you can await them:

await WriteImmoListAsync();   
await ReadImmoListAsync();

await WriteImmoListAsync();
await ReadImmoListAsync();   
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Thanks alot Stephen. To make them await i had to put them into a new async void method. Or is there a way to call them from the constructor? – 3009Robin Jun 03 '16 at 06:09
  • @3009Robin: I do not recommend `async void`. "Async constructors" are tricky; they're an indication that the object model isn't quite right. I have a [blog post on the subject](http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html). – Stephen Cleary Jun 03 '16 at 12:51
0

You can't start the methods again until you wait for them to complete. What that above code is trying to do is to write to a file, but while that's processing, it tries to open the file and write to it while the first method call hasn't completed. You need to wait for those method calls to finish before running them again - using the await keyword would be helpful here

Jeremy Kato
  • 467
  • 5
  • 12
0

It might be that the process writing/reading the file are still attached to the file. You might want to take a look at this pattern for async file read/write from Microsoft:

https://msdn.microsoft.com/en-ca/library/mt674879.aspx

Also, note that if the read and write are done from differents process, you're going to have to use a mutex. Here's a great explanation on how it works:

What is a good pattern for using a Global Mutex in C#?

Community
  • 1
  • 1
PhilDulac
  • 1,305
  • 20
  • 32