1

私は通常の.NETアプリケーションを持っています。この場合、MEFによってインポートされているパーツがあります。正常にインポートされますが、ある時点で、オブジェクトのリストをファイルに保存したいと思います。この場合、ハイスコアのリストを保存するだけです。

class HighScores
{
    static HighScores()
    {
        CheckTrust();
    }

    [ImportingConstructor]
    public HighScores(
         [Import("/Services/LoggingService", typeof(ILoggingService))] 
         ILoggingService l
        )
    {
        logger = l;

    }

    private ILoggingService logger { get; set; }

    public IEnumerable<HighScore> Scores
    {
        get
        {
            return m_Scores;
        }
    }
    private List<HighScore> m_ScoresUnsorted = new List<HighScore>();
    private readonly ObservableCollection<HighScore> m_Scores = 
        new ObservableCollection<HighScore>();

    public void LogNewHighScore(string name, int score, int level)
    {
        m_ScoresUnsorted.Add(new HighScore(name, score, level));
        CreateObservable();

        if (IsFullTrust)
        {
            Stream stream = null;
            try
            {
                // this line causes exception
                stream = new FileStream("HighScores.dat", 
                         System.IO.FileMode.Create, FileAccess.Write);  
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(stream, m_ScoresUnsorted);
            }
            catch (Exception e)
            {
                logger.Error("Error writing high scores:", e);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }
        }
    }

    private void CreateObservable()
    {
        m_ScoresUnsorted.Sort();
        m_Scores.Clear();
        for(int i = m_ScoresUnsorted.Count-1; i >= 0; i--)
        {
            m_Scores.Add(m_ScoresUnsorted[i]);
        }
    }

    static private void CheckTrust()
    {
        try
        {
            FileIOPermission permission =
                new FileIOPermission(PermissionState.Unrestricted);
            s_FullTrust = SecurityManager.IsGranted(permission);
        }
        catch (Exception)
        {
            // ignore
        }
    }

    static private bool s_FullTrust;
    static public bool IsFullTrust
    {
        get
        {
            return s_FullTrust;
        }
    }

}

新しいFileStream行でSystem.Security.SecurityExceptionが発生します。奇妙なことに、これをTextWriterに置き換えるだけで、機能します。何が間違っているのかわかりません。

編集:詳細...このコードをコンストラクターに入れると、実行されます。コールスタックをたどると(上記のサンプルに割り込む場合)、GUIスレッドで実行されているように見えます。具体的には、WPFディスパッチャーは、PropertyChangedイベントが発生したという事実に基づいて、プロパティに対してget操作を実行しています。では、おそらく、WPFのGUIリフレッシャーがファイルI/Oの実行を許可されていないことに関係しているのでしょうか。この種の意味はあります...ファイル書き込みのようなもののためにGUIをロックしたくないでしょう...

4

1 に答える 1

0

ストリーム機能を取得し、次のように「安全でない」ThreadPoolスレッドに配置することで、実行させることができました。

        ThreadPool.UnsafeQueueUserWorkItem(ignoredState =>
        {
            Stream stream = null;
            try
            {
                stream = new FileStream("HighScores.dat", System.IO.FileMode.Create, FileAccess.Write);
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(stream, "Test String");
            }
            catch (Exception e)
            {
                logger.Error("Error writing high scores:", e);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }
        }, null);

もちろん、これには同期に関する非常に悪い問題がたくさんあり、クリーンアップする必要がありますが、機能します。私がやろうとしていることは、スレッド内でロックしてリストのコピーを作成させてから、そのコピーをディスクに書き込むことだと思います。複数のスレッド間でロガーに安全にアクセスできないため、ロガーも削除する必要があります。

でも、なぜこれをしなければならないのかを知っていればよかったのに。

于 2009-10-28T04:29:48.080 に答える