我有一个常规的.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 ......
答案 0 :(得分: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);
当然,这有很多非常糟糕的同步问题,我必须清理,但它确实有效。我想我要做的就是锁定线程内部并让它复制列表,然后将副本写入磁盘。我不得不摆脱记录器,因为你不能安全地访问多个线程。
真的希望我知道为什么我必须这样做。