首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何避免TypeInitializer异常?

如何避免TypeInitializer异常?
EN

Stack Overflow用户
提问于 2012-11-26 04:16:08
回答 2查看 312关注 0票数 2

在应用程序中有2页,CompletePoll.aspx,Default.aspx。

CompletePoll.aspx -> Page_Load()

代码语言:javascript
复制
          Ultoo u = new Ultoo();
          u.UserName = Request["username"].ToString();
          u.Password = Request["password"].ToString();
          new Thread(u.CompletePoll).Start();

CompletePoll()

代码语言:javascript
复制
          .......
          .......
          String str = "Question:" + QuestionGenerator.GetNextQuestion(); /*Here i am getting Type initializer exception*/
          .......
          .......

QuestionGenerator

代码语言:javascript
复制
          public static class QuestionGenerator
          {
               private static string[] FirstParts = new StreamReader(HttpContext.Current.Server.MapPath("App_Data/QuestionPart1.txt")).ReadToEnd().Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
               private static string[] SecondParts = new StreamReader(HttpContext.Current.Server.MapPath("App_Data/QuestionPart2.txt")).ReadToEnd(). Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
               private static Random r = new Random();

               public static string GetNextQuestion()
               {
                    return FirstParts[r.Next(0, FirstParts.Length - 1)] + " " + SecondParts[r.Next(0, SecondParts.Length - 1)] + "?";
               }
          }

但是,如果我先调用Default.aspx,然后调用CompletePoll.aspx,则代码运行良好。

Default.aspx -> Page_Load()

代码语言:javascript
复制
         Label1.Text = QuestionGenerator.GetNextQuestion();

因此,这里我的问题是,如果我要访问CompletePoll.aspx first,则会得到TypeInitializer异常。如果我先访问Default.aspx,然后访问CompletePoll.aspx,则不会遇到任何问题。我的代码有什么问题,我是不是漏掉了什么?如何首先访问CompletePoll.aspx?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-11-26 09:36:52

私有静态StreamReader(HttpContext.Current.Server.MapPath("App_Data/QuestionPart1.txt")).ReadToEnd().Split(new FirstParts =新的string[] string[] { "\r\n“},StringSplitOptions.RemoveEmptyEntries);

这不对。当类型初始化时,它只检查一次HttpContext.Current,保存结果,并且不再尝试读取它。当第一次成功时,永不再检查可能是正确的,但是第一次检查将要求HttpContext.Current不是null。如果第一次尝试导致异常,则不会在以后重新初始化。您不能确定类是什么时候初始化的,因此不能确定HttpContext.Current是否设置在这个点上(如果您从线程调用它,则不会设置)。

而且,这不会调用StreamReader.Dispose,因此它将保持读取器并打开文件,直到垃圾收集器碰巧运行为止。

一种更安全的方法是

代码语言:javascript
复制
private static string[] firstParts; // field

private static string[] FirstParts // property
{
    get
    {
        if (firstParts == null)
        {
            using (var reader = new StreamReader(HttpContext.Current.Server.MapPath("App_Data/QuestionPart1.txt")))
                firstParts = reader.ReadToEnd().Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
        }
        return firstParts;
    }
}

这将确保调用reader.Dispose(),确保在首次访问属性时读取文件,而不是在初始化类型时读取文件,确保任何异常都以更直观的方式告诉您发生了什么,并确保即使FirstParts无法设置,类型的其余部分也是可用的。

但是,它仍然要求您不从线程读取FirstParts。您可以通过在启动线程之前阅读它一次来避免这个问题:

代码语言:javascript
复制
Ultoo u = new Ultoo();
u.UserName = Request["username"].ToString();
u.Password = Request["password"].ToString();
QuestionGenerator.Initialize(); // from the main thread
new Thread(u.CompletePoll).Start();


public static class QuestionGenerator
{
    public static void Initialize()
    {
        var firstParts = FirstParts;
        var secondParts = SecondParts;
        // merely reading the properties is enough to initialise them, so ignore the results
    }
}

一旦线程启动,在调用Initialize()之后,您可以可靠地访问FirstPartsSecondParts

票数 1
EN

Stack Overflow用户

发布于 2012-11-26 09:19:47

您需要查看内部异常。TypeInitializerException仅仅意味着从构造函数中抛出了异常。异常将由调用QuestionGenerator.GetNextQuestion()中包含的代码生成;

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13558564

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档