programing

TextBox에 추가하는 이유는 무엇입니까?루프 중에 텍스트가 반복될 때마다 더 많은 메모리를 차지합니까?

linuxpc 2023. 4. 16. 14:41
반응형

TextBox에 추가하는 이유는 무엇입니까?루프 중에 텍스트가 반복될 때마다 더 많은 메모리를 차지합니까?

간단한 질문

18만 번을 도는 루프가 있어요각 반복의 마지막에 결과를 TextBox에 추가하도록 되어 있으며, TextBox는 실시간으로 업데이트됩니다.

「」를 사용합니다.MyTextBox.Text += someValue애플리케이션이 대량의 메모리를 소비하게 되어, 몇천개의 레코드가 행해지면 사용 가능한 메모리가 부족하게 됩니다.

인 텍스트 ?TextBox.Text18달러?

편집 이 특정 케이스의 결과는 별로 중요하지 않습니다만, 이것이 메모리 부족인 것 같은 이유와 텍스트 상자에 텍스트를 추가하는 보다 효율적인 방법이 있는지 알고 싶습니다.


긴 (오리지널) 질문

CSV 파일의 ID 번호 리스트를 읽어, 각각의 PDF 리포트를 생성하는 작은 앱이 있습니다.되면 PDF 파일이 됩니다.ResultsTextBox.Text처리된 보고서와 정상적으로 처리된 보고서의 ID 번호가 추가됩니다.프로세스는 백그라운드 스레드에서 실행되므로 결과는항목이 처리됨에 따라 텍스트 상자가 실시간으로 업데이트됩니다.

저는 현재 18만 개의 ID 번호로 앱을 실행하고 있지만, 시간이 지날수록 애플리케이션이 차지하는 메모리는 기하급수적으로 증가하고 있습니다.약 90K부터 시작하지만 약 3000개의 레코드가 약 250MB, 4000개의 레코드가 응용 프로그램이 약 500MB의 메모리를 차지합니다.

TextBox에는 약 되어 있기 에 Results TextBox를 쓰는 할 수 .ResultsText.Text += someValue기억을 먹어버리는 원인이라는 거죠

제 질문은, 왜 이런 걸까요?TextBox에 데이터를 추가하는 더 좋은 방법은 무엇입니까?기억이 안 나는 문자요?

코드는 다음과 같습니다.

try
{
    report.SetParameterValue("Id", id);

    report.ExportToDisk(ExportFormatType.PortableDocFormat,
        string.Format(@"{0}\{1}.pdf", new object[] { outputLocation, id}));

    // ResultsText.Text += string.Format("Exported {0}\r\n", id);
}
catch (Exception ex)
{
    ErrorsText.Text += string.Format("Failed to export {0}: {1}\r\n", 
        new object[] { id, ex.Message });
}

또한 이 앱은 일회성으로 모든 보고서를 생성하는 데 몇 시간(또는 며칠)이 걸린다는 것은 중요하지 않다는 것을 언급할 가치가 있습니다.가장 우려되는 것은 시스템 메모리 한계에 도달하면 작동이 중지된다는 것입니다.

작업을 결과 박스의 두어도 를 에 이 있는지 .TextBox.Text이치노

메모리 사용량이 많은 이유는 텍스트 상자가 스택을 유지하여 사용자가 텍스트를 원래대로 되돌리거나 다시 저장할 수 있기 때문이라고 생각합니다.이 기능은 필요 없을 것 같으니 false로 설정해 보십시오.

TextBox.AppendText(someValue)TextBox.Text += someValueTextBox text 、 TextBox 、 TextBox 、 TextBox 。텍스트. StringBuilder와 마찬가지로 사용자가 무언가를 추가할 때마다 전체 텍스트 복사본이 생성되지 않습니다.

것 요.IsUndoEnabled플래그를 표시합니다.

텍스트 속성에 직접 추가하지 마십시오.추가에 StringBuilder를 사용한 후 완료되면 .text를 stringbuilder에서 종료된 문자열로 설정합니다.

텍스트 상자를 사용하는 대신 다음을 수행합니다.

  1. 만약을 위해 텍스트 파일을 열고 오류를 로그 파일로 스트리밍합니다.
  2. 목록 상자 컨트롤을 사용하여 오류를 나타내면 대량의 문자열이 복사되지 않습니다.

개인적으로는 항상 *를 사용합니다.몇 년 전 Stack Overflow에서 자주 사용되는 메서드를 비교한 프로파일링 통계를 가진 질문을 읽은 것으로 기억합니다.string.Concat

그럼에도 불구하고, 내가 찾을 수 있는 가장 좋은 것은 이 참조 질문특정 vs. 질문입니다.String.Format는 을 합니다.StringBuilder에 당신의 이 다른 곳에있는 것은 하는 이 듭니다.당신의 기억력이 다른 곳에 있는 건 아닌지 궁금하네요.

** James의 코멘트를 바탕으로 저는 웹 기반 개발에 주력하고 있기 때문에 무거운 문자열 포맷은 절대 하지 않습니다.*

TextBox에 대해 다시 생각해보시겠습니까?문자열 항목을 유지하는 ListBox의 성능이 향상될 수 있습니다.

그러나 가장 큰 문제는 18만 개의 아이템을 표시하는 것은 (인간의) 사용자를 대상으로 할 수 없으며 "실시간"에서 이를 변경하는 것도 아니라는 요구 사항인 것 같습니다.

바람직한 방법은 데이터의 샘플이나 진행률 표시기를 표시하는 것입니다.

불량 사용자로 덤프할 경우 배치 문자열이 업데이트됩니다.1초당 2개 또는 3개 이상의 변경을 지정할 수 있는 사용자는 없습니다.그래서 100초당 생산하면 50명씩 그룹을 만드세요.

몇몇 반응은 그것을 암시하고 있지만, 아무도 그것을 노골적으로 말하지 않아 놀랍다.String은 불변입니다.즉, String을 작성한 후에는 변경할 수 없습니다.따라서 기존 String에 연결할 때마다 새로운 String Object를 작성해야 합니다.String 객체와 관련된 메모리도 당연히 생성해야 합니다.이 메모리는 스트링이 커짐에 따라 가격이 비싸질 수 있습니다.대학 시절 허프만 부호화 압축을 하는 자바 프로그램에서 스트링을 연결하는 아마추어 실수를 한 적이 있습니다.여기에 기재되어 있는 일부에서 언급했듯이, 대량의 텍스트를 연결할 때 String Builder를 단순히 사용할 수 있었을 경우 String 연결로 인해 큰 피해가 발생할 수 있습니다.

권장되는 대로 String Builder를 사용합니다.String Builder를 인스턴스화할 때 최종 문자열 크기를 예측한 후 이 숫자를 사용하십시오.StringBuilder sb = 새로운 StringBuilder(estSize);

TextBox를 업데이트할 때 할당(예: textbox.text = sb)을 사용하십시오.ToString();

위와 같은 크로스 스레드 조작을 감시합니다.단, Begin 사용호출합니다. UI를 업데이트하는 동안 백그라운드 스레드를 차단할 필요가 없습니다.

A) 도입부: 이미 언급, 사용StringBuilder

B) 포인트: 너무 자주 업데이트하지 마십시오.

DateTime dtLastUpdate = DateTime.MinValue;

while (condition)
{
    DoSomeWork();
    if (DateTime.Now - dtLastUpdate > TimeSpan.FromSeconds(2))
    {
        _form.Invoke(() => {textBox.Text = myStringBuilder.ToString()});
        dtLastUpdate = DateTime.Now;
    }
}

C) 일회성 작업인 경우 x64 아키텍처를 사용하여 2Gb 제한을 유지합니다.

StringBuilderViewModel스트링 리바인딩의 혼란을 회피하여MyTextBox.Text이 시나리오에서는 퍼포먼스가 몇 배 향상되어 메모리 사용량이 감소합니다.

백그라운드 스레드에서 작업을 수행하더라도 UI 요소 자체는 메인 스레드 자체(WinForms)에서 업데이트되어야 합니다.

텍스트 상자를 업데이트할 때 다음과 같은 코드가 있습니까?

if(textbox.dispatcher.checkAccess()){
    textbox.text += "whatever";
}else{
    textbox.dispatcher.invoke(...);
}

그렇다면 UI 업데이트로 인해 백그라운드 작업이 확실히 병목현상을 겪고 있는 것입니다.

위에서 설명한 바와 같이 백그라운드 op에서 String Builder를 사용하는 것이 좋습니다.단, 텍스트 박스를 사이클마다 갱신하는 것이 아니라 정기적으로 갱신하여 퍼포먼스가 향상되는지 확인합니다.

편집 메모: WPF를 사용하지 않았습니다.

기억력이 기하급수적으로 증가한다고 하셨잖아요아니요, 이는 2차 성장, 즉 다항식 성장이며, 지수 성장만큼 극적인 것은 아닙니다.

다음 항목 수를 포함하는 문자열을 만들고 있습니다.

1 + 2 + 3 + 4 + 5 ... + n = (n^2 + n) /2.

와 함께n = 180,000총 메모리 할당이 완료됩니다.16,200,090,000 items,예.16.2 billion items이 메모리는 한 번에 할당되는 것은 아니지만, GC(쓰레기 수집기)에 대한 청소 작업이 매우 많습니다.

또한 이전 문자열(증가 중인 문자열)을 새 문자열에 179,999번 복사해야 합니다.복사된 바이트의 총 수n^2역!!

리스트 박스여기서는 큰 문자열을 작성하지 않고 새 문자열을 추가할 수 있습니다. a.StringBuild중간 결과도 표시해야 하기 때문에는 도움이 되지 않습니다.

언급URL : https://stackoverflow.com/questions/8733887/why-does-appending-to-textbox-text-during-a-loop-take-up-more-memory-with-each-i

반응형