C# 创建新文件流时System.Security.SecurityException
我有一个常规的.NET应用程序。在这种情况下,我有一个部件是由MEF进口的。它可以很好地导入,但在某一点上,我想将对象列表保存到文件中。在这种情况下,它只是保存一个高分列表:C# 创建新文件流时System.Security.SecurityException,c#,filestream,mef,securityexception,C#,Filestream,Mef,Securityexception,我有一个常规的.NET应用程序。在这种情况下,我有一个部件是由MEF进口的。它可以很好地导入,但在某一点上,我想将对象列表保存到文件中。在这种情况下,它只是保存一个高分列表: class HighScores { static HighScores() { CheckTrust(); } [ImportingConstructor] public HighScores( [Import("/Services/Loggin
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;
}
}
}
班级高分
{
静态高分()
{
CheckTrust();
}
[导入构造函数]
公开高分(
[导入(“/Services/LoggingService”,typeof(ILoggingService))]
伊洛金服务公司
)
{
记录器=l;
}
专用iLogginService记录器{get;set;}
公共数字分数
{
收到
{
返回m_分数;
}
}
私有列表m_scoresSorted=新列表();
私有只读可观察收集m_分数=
新的可观察集合();
public void LogNewHighScore(字符串名称、整数分数、整数级别)
{
m_ScoresSorted.Add(新的高分(姓名、分数、级别));
CreateObservable();
如果(完全信任)
{
Stream=null;
尝试
{
//这一行导致异常
stream=新文件流(“HighScores.dat”,
System.IO.FileMode.Create、FileAccess.Write);
BinaryFormatter b=新的BinaryFormatter();
b、 序列化(流,m_scoresorted);
}
捕获(例外e)
{
logger.Error(“错误写入高分:”,e);
}
最后
{
if(流!=null)
{
stream.Close();
}
}
}
}
私有void CreateObservable()
{
m_scoresSorted.Sort();
m_分数。清除();
对于(int i=m_scoresSorted.Count-1;i>=0;i--)
{
m_分数。添加(m_分数排序[i]);
}
}
静态私有void CheckTrust()
{
尝试
{
FileIOPermission权限=
新的FileIOPermission(PermissionState.Unrestricted);
s_FullTrust=SecurityManager.isgrated(权限);
}
捕获(例外)
{
//忽略
}
}
静态私有bool s_FullTrust;
静态公共bool是完全信任的
{
收到
{
让s_完全信任;
}
}
}
我在新的FileStream行中收到System.Security.SecurityException。奇怪的是,如果我用一个文本编写器来代替它,它就会工作。我不明白我做错了什么
编辑:更多信息。。。当我将此代码放入构造函数时,它会执行。如果按照调用堆栈返回(在上面的示例中中断时),它似乎正在GUI线程上执行。特别是WPF调度程序正在基于触发PropertyChanged事件的事实对属性运行get操作。所以,也许这与WPF中的GUI刷新器不允许执行文件I/O有关?这种说法有道理。。。您不想为文件写入之类的事情锁定GUI…我可以通过使用流功能并将其放在“不安全”的线程池线程上来执行它,如下所示:
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);
当然,这有一大堆非常糟糕的同步问题,我必须清理,但它是有效的。我想我要做的是锁定线程,让它复制列表,然后将副本写入磁盘。我也必须摆脱记录器,因为您无法跨多个线程安全地访问它
真希望我知道为什么我要这么做