记忆异常; NullReference; CA1001实现IDisposable

时间:2014-05-11 12:20:57

标签: c# out-of-memory nullreferenceexception idisposable

我有一个小程序,它从文本文件中获取链接,将这些链接传递给ImportIO的后端系统,并将结果保存为CSV。但是我在运行15,20分钟后看到了以下错误。我遇到两个例外,以先到者为准 1. System.OutOfMemoryException 要么 2. System.NUllReferenceException 然而,这两个都是我在代码中的某个地方感到我的错。我不是专家,但我尝试使用计时器,关闭文件,甚至将对象设置为null。没有工作甚至使用ArgumentNullException。 我运行了代码分析,它建议我应该忽略这个错误。

  

CA1001拥有一次性领域的类型应为一次性工具   可以在'ImportIO'上使用IDis,因为它会创建以下成员   IDisisable类型:'BlockingCollection>'。 Ostock Main.cs 232

我的代码如下,我不包括importIO类,它很长。我认为解决方案很简单,但我不是正确的道路。你能帮忙吗?

namespace MinimalCometLibrary
{
    class Program
    {
        private static CountdownEvent countdownLatch;
        static void Main(string[] args)
        {            
            string[] lines = File.ReadAllLines(@"C:\Users\James\Desktop\Exper\Input_Links\Stock_links.txt");
            for (int i = 0; i < lines.Length; i++)
            {                
                string[] line = lines[i].Split(new string[] { "\t" }, StringSplitOptions.RemoveEmptyEntries);
                for (int j = 0; j < line.Length; j++)
                {

                 ImportIO io = new ImportIO("https://query.import.io", Guid.Parse("sdasd-asdasd-NoReal-3easdecb"), "NoReal=");
                /* Time Starts
                    Stopwatch sw = new Stopwatch(); // sw cotructor
                    sw.Start(); // starts the stopwatch
                    for (int b = 0; ; b++)
                    {
                        if (b % 1000 == 0) // if in 100000th iteration (could be any other large number
                        // depending on how often you want the time to be checked) 
                        {
                            sw.Stop(); // stop the time measurement
                            if (sw.ElapsedMilliseconds > 25) // check if desired period of time has elapsed
                            {
                                break; // if more than 5000 milliseconds have passed, stop looping and return
                                // to the existing code
                            }
                            else
                            {
                                sw.Start(); // if less than 5000 milliseconds have elapsed, continue looping
                                // and resume time measurement
                            }
                        }
                    }
                //Time Ends 
                 */   
                    io.Connect();
                    countdownLatch = new CountdownEvent(1);
                    // Query for tile SamsClub_Extractor, line[j]
                    Dictionary<String, Object> query1 = new Dictionary<string, object>();
                    query1.Add("input", new Dictionary<String, String>() { { "webpage/url", line[j] } });
                    query1.Add("connectorGuids", new List<String>() { "189f34f3-0f82-4abb-8fbc-f353f35a255a" });
                    io.DoQuery(query1, HandleQuery);
                    countdownLatch.Wait(); 
                    io.Disconnect();

                }        

            }

            Environment.Exit(0);


        }


       private static void HandleQuery(Query query, Dictionary<String, Object> message)
        {

            if (message["type"].Equals("MESSAGE"))
            {
                Console.WriteLine("Got data!");
                string JSON = JsonConvert.SerializeObject(message["data"]);
                //Deserialize to strongly typed class i.e., RootObject
                RootObject obj = JsonConvert.DeserializeObject<RootObject>(JSON);

        // handle null reference
                if (obj == null) { throw new ArgumentNullException("PleaseKeepRunning"); }


                //loop through the list and write to CSV file
                foreach (Result resultsItem in obj.results)
                {
                    Console.WriteLine(resultsItem.itemnbr + "-" + resultsItem.price +
                           "-" + resultsItem.product_name + "_" + obj.pageUrl);                   
                    string filePath = @"C:\Users\James\Desktop\Exper\Output_Files\StockPrice_NOW.txt";

                    //checking if file already exists, if not, create it:
                    if (!File.Exists(filePath))
                    {
                        FileStream fs = new FileStream(filePath, FileMode.CreateNew);
                        fs.Close();
                    }

                    //writing to a file (appending text):
                    using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write))
                    {
                        using (TextWriter tw = new StreamWriter(fs))
                            tw.WriteLine(resultsItem.itemnbr + "\t" + resultsItem.price + "\t" + resultsItem.product_name + "\t" + resultsItem.misc + 
                           "\t" +  resultsItem.qty + "\t" + obj.pageUrl);
                        fs.Close();
                    }

                    //Set object to null
                    obj = null;
                    obj.results = null;
                }

            }

            if (query.isFinished) countdownLatch.Signal();

        }        

   }    

//root Object

    public class Result
{

    public double price { get; set; }    
    public string itemnbr { get; set; }
    public string product_name { get; set; }
    public string qty { get; set; }
    public string misc { get; set; }
}

public class RootObject
{
    public List<string> cookies { get; set; }
    public List<Result> results { get; set; }
    public string pageUrl { get; set; }
    public string connectorGuid { get; set; }
    public string connectorVersionGuid { get; set; }
    public int offset { get; set; }
}

请原谅我在.net上的有限知识。我完全是新手。 :) 感谢

----编辑 我按照建议使用了dispose和use,但我仍然面临错误。我看到错误异常,调试器在importIO中突出显示这行代码。

  

new Thread(new ThreadStart(PollQueue))。Start();

我还观察到stock.vshost.exe * 32在70MB之后的任何时候都会不断增加内存并抛出内存异常。我包含了importIO类代码

class ImportIO 
    {
        private String host { get; set; }
        private int port { get; set; }


        private Guid userGuid;
        private String apiKey;


        private static String messagingChannel = "/messaging";
        private String url;


        private int msgId = 0;
        private String clientId;


        private Boolean isConnected;


        CookieContainer cookieContainer = new CookieContainer();


        Dictionary<Guid, Query> queries = new Dictionary<Guid, Query>();


        private BlockingCollection<Dictionary<String, Object>> messageQueue = new BlockingCollection<Dictionary<string, object>>();


        public ImportIO(String host = "http://query.import.io", Guid userGuid = default(Guid), String apiKey = null)
        {
            this.userGuid = userGuid;
            this.apiKey = apiKey;


            this.url = host + "/query/comet/";
            clientId = null;
        }


        public void Login(String username, String password, String host = "http://api.import.io")
        {
            Console.WriteLine("Logging in");
            String loginParams = "username=" + HttpUtility.UrlEncode(username) + "&password=" + HttpUtility.UrlEncode(password);
            String searchUrl = host + "/auth/login";
            HttpWebRequest loginRequest = (HttpWebRequest)WebRequest.Create(searchUrl);


            loginRequest.Method = "POST";
            loginRequest.ContentType = "application/x-www-form-urlencoded";
            loginRequest.ContentLength = loginParams.Length;


            loginRequest.CookieContainer = cookieContainer;


            using (Stream dataStream = loginRequest.GetRequestStream())
            {
                dataStream.Write(System.Text.UTF8Encoding.UTF8.GetBytes(loginParams), 0, loginParams.Length);


                HttpWebResponse loginResponse = (HttpWebResponse)loginRequest.GetResponse();




                if (loginResponse.StatusCode != HttpStatusCode.OK)
                {
                    throw new Exception("Could not log in, code:" + loginResponse.StatusCode);
                }
                else
                {
                    foreach (Cookie cookie in loginResponse.Cookies)
                    {
                        if (cookie.Name.Equals("AUTH"))
                        {
                            // Login was successful
                            Console.WriteLine("Login Successful");
                        }
                    }


                }
            }
        }


        public List<Dictionary<String, Object>> Request(String channel, Dictionary<String, Object> data = null, String path = "", Boolean doThrow = true)
        {
            Dictionary<String, Object> dataPacket = new Dictionary<String, Object>();
            dataPacket.Add("channel", channel);
            dataPacket.Add("connectionType", "long-polling");
            dataPacket.Add("id", (msgId++).ToString());


            if (this.clientId != null)
                dataPacket.Add("clientId", this.clientId);


            if (data != null)
            {
                foreach (KeyValuePair<String, Object> entry in data)
                {
                    dataPacket.Add(entry.Key, entry.Value);
                }
            }


            String url = this.url + path;


            if (apiKey != null)
            {
                url += "?_user=" + HttpUtility.UrlEncode(userGuid.ToString()) + "&_apikey=" + HttpUtility.UrlEncode(apiKey);
            }


            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.AutomaticDecompression = DecompressionMethods.GZip;
            request.Method = "POST";
            request.ContentType = "application/json;charset=UTF-8";
            request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip");
            String dataJson = JsonConvert.SerializeObject(new List<Object>() { dataPacket });


            request.ContentLength = dataJson.Length;


            request.CookieContainer = cookieContainer;


            using (Stream dataStream = request.GetRequestStream())
            {
                dataStream.Write(System.Text.UTF8Encoding.UTF8.GetBytes(dataJson), 0, dataJson.Length);
                try
                {
                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();


                    using (StreamReader responseStream = new StreamReader(response.GetResponseStream()))
                    {
                        String responseJson = responseStream.ReadToEnd();
                        List<Dictionary<String, Object>> responseList = JsonConvert.DeserializeObject<List<Dictionary<String, Object>>>(responseJson);
                        foreach (Dictionary<String, Object> responseDict in responseList)
                        {
                            if (responseDict.ContainsKey("successful") && (bool)responseDict["successful"] != true)
                            {
                                if (doThrow)
                                    throw new Exception("Unsucessful request");
                            }


                            if (!responseDict["channel"].Equals(messagingChannel)) continue;


                            if (responseDict.ContainsKey("data"))
                            {
                                messageQueue.Add(((Newtonsoft.Json.Linq.JObject)responseDict["data"]).ToObject<Dictionary<String, Object>>());
                            }


                        }


                        return responseList;
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error occurred {0}", e.Message);
                    return new List<Dictionary<String, Object>>();
                }

            }


        }


        public void Handshake()
        {
            Dictionary<String, Object> handshakeData = new Dictionary<String, Object>();
            handshakeData.Add("version", "1.0");
            handshakeData.Add("minimumVersion", "0.9");
            handshakeData.Add("supportedConnectionTypes", new List<String> { "long-polling" });
            handshakeData.Add("advice", new Dictionary<String, int>() { { "timeout", 60000 }, { "interval", 0 } });
            List<Dictionary<String, Object>> responseList = Request("/meta/handshake", handshakeData, "handshake");
            clientId = (String)responseList[0]["clientId"];
        }


        public void Connect()
        {
            if (isConnected)
            {
                return;
            }

            Handshake();


            Dictionary<String, Object> subscribeData = new Dictionary<string, object>();
            subscribeData.Add("subscription", messagingChannel);
            Request("/meta/subscribe", subscribeData);


            isConnected = true;


            new Thread(new ThreadStart(Poll)).Start();


            new Thread(new ThreadStart(PollQueue)).Start();
        }


        public void Disconnect()
        {
            Request("/meta/disconnect", null, "", true);
            isConnected = false;
        }


        private void Poll()
        {
            while (isConnected)
            {
                Request("/meta/connect", null, "connect", false);
            }
        }


        private void PollQueue()
        {
            while (isConnected)
            {
                ProcessMessage(messageQueue.Take());
            }
        }


        private void ProcessMessage(Dictionary<String, Object> data)
        {
            Guid requestId = Guid.Parse((String)data["requestId"]);
            Query query = queries[requestId];


            query.OnMessage(data);
            if (query.isFinished)
            {
                queries.Remove(requestId);
            }
        }


        public void DoQuery(Dictionary<String, Object> query, QueryHandler queryHandler)
        {
            Guid requestId = Guid.NewGuid();
            queries.Add(requestId, new Query(query, queryHandler));
            query.Add("requestId", requestId);
            Request("/service/query", new Dictionary<String, Object>() { { "data", query } });
        }




    }

2 个答案:

答案 0 :(得分:0)

我不能说你的异常是否与它有关而没有看到完整的代码,但警告是关于“在”ImportIO中的问题,而不是在调用它的代码中(它抱怨ImportIO类没有实现IDisposable,而不是你做错了什么)

由于您使用类进行了编辑:只需在ImportIO类上实现IDisposable,这里有一个关于如何正确实现IDisposable的链接:Implementing IDisposable correctly

确保在处理ImportIO时丢弃BlockingCollection。

然后将ImportIO包装在一个使用中,警告应该消失。如果仅这一点引起了这些例外,我会感到惊讶,但这是解决警告的方法。

答案 1 :(得分:0)

尝试调用Dispose()方法,因为正如您的错误消息中所示,它是一个内存错误,因为您不断打开文件并读取它们然后将数据保存在内存中,导致您在一段时间后看到崩溃

试试这个:

     if (!File.Exists(filePath))
                {
                    FileStream fs = new FileStream(filePath, FileMode.CreateNew);
                    fs.Close(); 
                    fs.Dispose();
                }

还可以对ImportIO类使用using(){}

    using(ImportIO myIO = new ImportIO) {  }