1

私はAPIを設計しています。現在、ディスク容量が不足している状況を安全に処理しようとしています。基本的に、いくつかのデータを保持する一連のファイルがあります。ディスクがいっぱいになると、別のデータ ファイルを書き込もうとすると、もちろんエラーがスローされます。この時点で、1 つのファイルを削除します (ファイル リストを最も古いものから新しいものへとループし、ファイルを正常に削除した後で再試行します)。次に、ファイルの書き込みを再試行します。ファイルがエラーなしで書き込まれるまで、このプロセスを繰り返します。

今楽しい部分。これらはすべて同時に発生します。同様に、ある時点で、これを一度に実行する 8 つのスレッドがあります。これは物事を非常に興味深いものにし、奇妙なエラーにつながりました.

ここにコードがあります

    public void Save(string text, string id)
    {
        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        {
            var existing = store.GetFileNames(string.Format(Prefix + "/*-{0}.dat", id));
            if (existing.Any()) return; //it already is saved

            string name = string.Format(Prefix + "/{0}-{1}.dat", DateTime.UtcNow.ToString("yyyyMMddHHmmssfffffff"), id);
        tryagain:
            bool doover=false;
            try
            {
                AttemptFileWrite(store, name, text);
            }
            catch (IOException)
            {
                doover = true;
            }
            catch (IsolatedStorageException) //THIS LINE
            {
                doover = true;
            }
            if (doover)
            {
                Attempt(() => store.DeleteFile(name)); //because apparently this can also fail. 
                var files = store.GetFileNames(Path.Combine(Prefix, "*.dat"));
                foreach (var file in files.OrderBy(x=>x))
                {
                    try
                    {
                        store.DeleteFile(Path.Combine(Prefix, file));
                    }
                    catch
                    {
                        continue;
                    }
                    break;
                }
                goto tryagain; //prepare the velociraptor shield!
            }
        }
    }

    void AttemptFileWrite(IsolatedStorageFile store, string name, string text)
    {
        using (var file = store.OpenFile(
            name,
            FileMode.Create,
            FileAccess.ReadWrite,
            FileShare.None | FileShare.Delete
            ))
        {
            using (var writer = new StreamWriter(file))
            {
                writer.Write(text);
                writer.Flush();
                writer.Close();
            }
            file.Close();
        }
    }

    static void Attempt(Action func)
    {
        try
        {
            func();
        }
        catch
        {
        }
    }
    static T Attempt<T>(Func<T> func)
    {
        try
        {
            return func();
        }
        catch
        {
        }
        return default(T);
    }
    public string GetSaved()
    {

        string content=null;
        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
        {
            var files = store.GetFileNames(Path.Combine(Prefix,"*.dat")).OrderBy(x => x);

            if (!files.Any()) return new MessageBatch();
            foreach (var filename in files)
            {
                IsolatedStorageFileStream file=null;
                try
                {
                    file = Attempt(() =>
                        store.OpenFile(Path.Combine(Prefix, filename), FileMode.Open, FileAccess.ReadWrite, FileShare.None | FileShare.Delete));
                    if (file == null)
                    {
                        continue; //couldn't open. assume locked or some such
                    }
                    file.Seek(0L, SeekOrigin.Begin);
                    using (var reader = new StreamReader(file))
                    {
                        content = reader.ReadToEnd();
                    }
                    //take note here. We delete the file, while we still have it open!
                    //This is done because having the file open prevents other readers, but if we close it first,
                    //then there is a race condition that right after closing the stream, another reader could pick it up and 
                    //open exclusively. It looks weird, but it's right. Trust me. 
                    store.DeleteFile(Path.Combine(Prefix, filename));
                    if (!string.IsNullOrEmpty(content))
                    {
                        break;
                    }
                }
                finally
                {
                    if (file != null) file.Close();
                }
            }
        }
        return content;
    }

THIS LINE と記された行で、私が話していることです。AttemptFileWrite を実行するstore.AvailableSpaceと、データを格納するのに十分なスペースがあることを確認できますが、ファイルを開こうとすると、この IsolatedStorageException がスローされ、Operation Not Permitted. この奇妙なケースを除けば、他のすべてのケースでは、ディスクがいっぱいであるというメッセージとともに IOException がスローされるだけです。

奇妙な競合状態があるかどうか、またはこれが対処しなければならないエラーかどうかを把握しようとしていますか?

なぜこのエラーが発生するのですか?

4

0 に答える 0