C# WinForms 앱은 프로세서를 최대화하지만 힘든 일은 하지 않습니다!

StackOverflow https://stackoverflow.com/questions/1244143

  •  12-09-2019
  •  | 
  •  

문제

1.20Ghz 프로세서와 1GB RAM을 갖춘 넷북이 있습니다.

저는 5분 간격으로 텍스트 파일의 모든 줄을 읽고 해당 줄의 내용에 따라 건너뛰거나 xml 파일에 쓰는 C# WinForms 앱을 실행하고 있습니다.때로는 약 2000줄을 처리하는 경우도 있습니다.

이 작업을 시작하면 프로세서가 최대치에 도달하여 100% 사용됩니다.그러나 2.40Ghz 프로세서와 3GB RAM을 갖춘 내 데스크탑에서는 (분명한 이유로) 그대로 유지됩니다...실제로 이 프로세서 문제를 극적으로 줄일 수 있는 방법이 있습니까?코드가 복잡하지도 않고, 코딩도 나쁘지 않고, 파일을 계속 열고 읽고 쓰지도 않는데...모든 것이 단번에 이루어졌습니다.

어떤 도움이라도 크게 감사드립니다!?

샘플 코드

***시간제 노동자.....

#region Timers Setup

            aTimer.Tick += new EventHandler(OnTimedEvent);
            aTimer.Interval = 60000;
            aTimer.Enabled = true;
            aTimer.Start();
            radioButton60Mins.Checked = true;

            #endregion Timers Setup


private void OnTimedEvent(object source, EventArgs e)
        {
            string msgLoggerMessage = "Checking For New Messages " + DateTime.Now;
            listBoxActivityLog.Items.Add(msgLoggerMessage);
            MessageLogger messageLogger = new MessageLogger();
            messageLogger.LogMessage(msgLoggerMessage);

            if (radioButton1Min.Checked)
            {
                aTimer.Interval = 60000;
            }
            if (radioButton60Mins.Checked)
            {
                aTimer.Interval = 3600000;
            }
            if (radioButton5Mins.Checked)
            {
                aTimer.Interval = 300000;
            }

            // split the file into a list of sms messages
            List<SmsMessage> messages = smsPar.ParseFile(smsPar.CopyFile());

            // sanitize the list to get rid of stuff we don't want
            smsPar.SanitizeSmsMessageList(messages);

            ApplyAppropriateColoursToRecSMSListinDGV();
        }

public List<SmsMessage> ParseFile(string filePath)
        {
            List<SmsMessage> list = new List<SmsMessage>();
            using (StreamReader file = new StreamReader(filePath))
            {
                string line;
                while ((line = file.ReadLine()) != null)
                {
                    var sms = ParseLine(line);
                    list.Add(sms);
                }
            }
            return list;
        }

        public SmsMessage ParseLine(string line)
        {
            string[] words = line.Split(',');

            for (int i = 0; i < words.Length; i++)
            {

                words[i] = words[i].Trim('"');
            }
            SmsMessage msg = new SmsMessage();
            msg.Number = int.Parse(words[0]);
            msg.MobNumber = words[1];
            msg.Message = words[4];
            msg.FollowedUp = "Unassigned";
            msg.Outcome = string.Empty;

            try
            {

                //DateTime Conversion!!!
                string[] splitWords = words[2].Split('/');
                string year = splitWords[0].Replace("09", "20" + splitWords[0]);
                string dateString = splitWords[2] + "/" + splitWords[1] + "/" + year;
                string timeString = words[3];
                string wholeDT = dateString + " " + timeString;
                DateTime dateTime = DateTime.Parse(wholeDT);
                msg.Date = dateTime;

            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
                Application.Exit();
            }
            return msg;
        }

        public void SanitizeSmsMessageList(List<SmsMessage> list)
        {
            // strip out unwanted messages
            // list.Remove(some_message); etc...
            List<SmsMessage> remove = new List<SmsMessage>();
            foreach (SmsMessage message in list)
            {
                if (message.Number > 1)
                {
                    remove.Add(message);
                }
            }
            foreach (SmsMessage msg in remove)
            {
                list.Remove(msg);
            }
            //Fire Received messages to xml doc
            ParseSmsToXMLDB(list);
}

public void ParseSmsToXMLDB(List<SmsMessage> list)
        {
            try
            {
                if (File.Exists(WriteDirectory + SaveName))
                {
                    xmlE.AddXMLElement(list, WriteDirectory + SaveName);
                }
                else
                {
                    xmlE.CreateNewXML(WriteDirectory + SaveName);
                    xmlE.AddXMLElement(list, WriteDirectory + SaveName);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
                Application.Exit();
            }
        }

public void CreateNewXML(string writeDir)
        {
            try
            {
                XElement Database = new XElement("Database");
                Database.Save(writeDir);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

        public void AddXMLElement(List<SmsMessage> messages, string writeDir)
        {
            try
            {
                XElement Database = XElement.Load(writeDir);
                foreach (SmsMessage msg in messages)
                {
                    if (!DoesExist(msg.MobNumber, writeDir))
                    {
                        Database.Add(new XElement("SMS",
                              new XElement("Number", msg.MobNumber),
                              new XElement("DateTime", msg.Date),
                              new XElement("Message", msg.Message),
                              new XElement("FollowedUpBy", msg.FollowedUp),
                              new XElement("Outcome", msg.Outcome),
                        new XElement("Quantity", msg.Quantity),
                        new XElement("Points", msg.Points)));

                        EventNotify.SendNotification("A New Message Has Arrived!", msg.MobNumber);

                    }
                }
                Database.Save(writeDir);
                EventNotify.UpdateDataGridView();
                EventNotify.UpdateStatisticsDB();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

public bool DoesExist(string number, string writeDir)
        {
            XElement main = XElement.Load(writeDir);
            return main.Descendants("Number")
                      .Any(element => element.Value == number);
        }
도움이 되었습니까?

해결책

프로파일러 및/또는 성능 모니터 사용 및/또는 \\live.sysinternals.com\tools\procmon.exe 및/또는 ResourceMonitor를 사용하여 무슨 일이 일어나고 있는지 확인

다른 팁

5분 프로세스가 백그라운드 작업인 경우 스레드 우선 순위를 활용할 수 있습니다.

MSDN 여기.

별도의 스레드에서 처리를 수행하고 타이머를 System.Threading.Timer로 변경하고 콜백 이벤트를 사용하는 경우 해당 스레드에서 애플리케이션의 나머지 부분보다 낮은 우선 순위를 설정할 수 있습니다.

ParseFile 루프 내부에 다음을 추가해 볼 수 있습니다. 스레드.수면 및/또는 애플리케이션.DoEvents() 전화해서 도움이 되는지 알아보세요.별도의 스레드에서 구문 분석을 수행하는 것이 더 좋지만 최소한 이 간단한 테스트를 시도하여 도움이 되는지 확인할 수 있습니다.

캐치의 MessageBox에 크로스 스레드 문제가 발생할 수 있습니다.추적 출력에 쓰기 위해 교체해 보십시오.

어쨌든, 당신은 구체적인 조언을 얻는 데 도움이 되지 않는 전체 (작은) 프로그램을 게시했습니다.노력하다 삭제 중 메소드 본문을 과학적으로 한 번에 하나씩 문제가 발생/중지되도록 노력합니다.이는 문제를 찾고 질문에서 관련 없는 부분을 제거하는 데 도움이 될 것입니다(자신과 SO 모두에게).

현재 처리 모델은 배치 기반입니다. 구문 분석을 수행한 다음 메시지를 처리하는 등의 작업을 수행합니다.

Linq 스타일의 "풀" 접근 방식으로 전환하면 메모리 오버헤드가 줄어들 가능성이 높습니다.

예를 들어, ParseFile() 방법은 다음과 같습니다.

public IEnmerable<SmsMessage> ParseFile(string filePath)
{
    using (StreamReader file = new StreamReader(filePath))
    {
        string line;
        while ((line = file.ReadLine()) != null)
        {
            var sms = ParseLine(line);
            yield return sms;
        }
    }
}

장점은 모든 메시지를 한 번에 구문 분석한 다음 모두 처리하는 대신 각 SmsMessage를 생성된 대로 처리할 수 있다는 것입니다.

이렇게 하면 넷북과 데스크탑 간의 성능 차이를 발생시키는 가장 큰 원인 중 하나인 메모리 오버헤드가 줄어듭니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top