2009-10-28 17 views
1

我有一個普通的.NET應用程序。在這種情況下,我有一個由MEF導入的部分。它導入正常,但在某個時候,我想將對象列表保存到文件中。在這種情況下,它只是節省了高分的列表:當創建一個新的FileStream時產生System.Security.SecurityException

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有關?這種說法是有道理的...你不想鎖定圖形用戶界面,像文件寫入...

回答

0

我能夠通過將流功能並將其放在「不安全」線程池線程,就像這樣:

 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); 

當然,有一大堆,我要清理非常糟糕的同步問題,但它的作品。我認爲我要做的就是鎖定線程並讓它創建列表的副本,然後將副本寫入磁盤。我不得不擺脫記錄器,因爲你無法安全地訪問跨多個線程。

真的希望我知道爲什麼我不得不這樣做。

相關問題