C# 스레드 반복 처리시 cpu 점유율 문의

안녕하세요 C# 스레드 처리 관련 해서 문의 드립니다.

현재 특정 이벤트가 가 발생 할 때 마다 스레드를 호출 하도록 코딩을 하였습니다.

이렇게 하다 보니까 cpu 사용율이 거의 50% 이상 잡아 먹게 되어서

컴퓨터가 느려지는 현상이 있습니다 .

이 문제를 해결 하기 위해서 스레드 풀 을 사용해서 처리 해보았으나

실시간으로 데이터가 변경 되면서 반영을 해야 하다 보니 스레드 풀은 사용하지 못하는 실정 입니다.

사용 못하는 이유는 이벤트가 워낙 많이 발생 하다 보니 해당 이벤트에서 대부분 스레드를

다 사용해 버려서 다른 독립 스레드 들이 동작이 지연 되는 현상이 있습니다.

(조회를 눌렀는데 바로 안되고 다른 스레드 들이 다 처리가 되어야만 그때 서야 조회가 되는 현상)

반복 적인 스레드 가 하는 일은 WInform 에서 조회 버튼 눌렀을 때 특정 데이터를 가져 오고

데이터를 가져 온 순간 부터 데이터가 실시간 으로 변화가 발생 되는데

변화가 될 때 마다 변경이 발생된 그리드 Cell(칸) 에 색상을 빨강으로 변경 했다가 1초 뒤에 다시

원래 색으로 돌려주는 기능을 스레드 처리 했습니다.

그러다 보니 이벤트가 적게 발생 되면 문제가 없으나 이벤트가 무수히 많이 발생 되게 되면

스레드를 많이 호출 하게 되서 cpu 사용율이 많이 올라갑니다.

제가 구현 하고자 하는 방법에서 스레드를 지속적으로 계속 호출 하는 방법 말고

다른 방법으로 구현 할 수 있는게 있을까요?

재현 되는 샘플 프로젝트나

관련 코드 한줄도 없이.,

문제를 논하기는 어려울 것 같습니다.


'아무런 정보 없이 많이 느립니다. 다른 방법은 없을까요?' 보단
'이런 코드가 CPU점유율이 50%이상 차지하는데 더 어떤 문제점이 있을까요?' 가 더 좋지 않을까요?
3개의 좋아요

어짜피 윈폼에서는 UI 렌더링을 한개의 스레드(UI스레드)에서 하기 때문에 이벤트 발생시 색 변경(애니메이션)을 건별로 스레드에서 처리하는 것은 효과적이지 못합니다. 그리고 건수가 얼마나 많길래 CPU 사용율이 50% 이상이나 차지하지요??

실행되는 코드를 첨부 주시면 좀 더 효과적으로 답변 드릴 수 있을 것 같습니다.

이런 전개로 변경 작업 하시면 효과적이지 않을까 합니다.

  • 이벤트 수신 → 메시지 큐로 저장
  • 특정 스레드 (한개)가 1초 간격(또는 특정 간격)으로 메시지 큐에 정보가 있다면 그리드 일괄 갱신
3개의 좋아요

간단한 샘플 코드를 작성 하자면

Thread Thr = null;

//그리드 Cell 이 변경 될 때 마다 호출 되는 이벤트 (수시로 호출됨.)
private void Grid_Change_Event (CellEvent e)
{
    e.Cell.Color = Color.Read;

    Thr = new Thread(() => Run(e));
    Thr.IsBackgroud = True;
    Thr.Start();      
}

private void Run(CellEvent e)
{
    Thread.Sleep(1000);
    e.Cell.Color = Color.Black;
}

단순 하게는 이런 코드 입니다.

“Grid_Change_Event” 해당 이벤트가 1초에도 10번 이상 호출 될 정도로

잦은 호출이 발생 되고 있으며 그 이벤트 안에 스레드 처리를 넣음으로써

데이터가 실시간 으로 변경 되고 있음을 사용자 한테 시각적으로 알림 형태를 보여 줄 수 있도록

구현 하였습니다.

그리드 Row, Col 이 만약 3X3 이라고 하면

총 9칸이 생기는데 1칸 자체를 Cell 이라 부릅니다. 이게 평균적으로 100개 정도 생긴다고 보면 되고

이 100개의 Cell 이 개별로 데이터 값이 변경 되었을 때 해당 Cell 에 색상을 변경 시켜주고

1초 뒤에 다시 변경 해줘야 합니다. (이론적으로 동시에 이벤트가 100개도 발생 될 수 있음)

그래서 이벤트가 수시로 호출 되는 것 입니다.

1개의 좋아요

일단 숙지하셔야 할 것이 하나 있는데, 백그라운드에서 아무리 병렬 처리를 잘 한다고 해도 결국 이것을 표시하는 UI는 스레드 하나로 모든 것을 처리하게 됩니다. 그래서 UI에 데이터를 표시하는 것과 다른 스레드가 실행되는 것을 분리해서 프로그래밍하셔야 할 것 같습니다. 다중 스레드를 이용할 때에는 서로 다른 스레드 간에 "기다리는 일"을 만들지 않는 것이 성능에서 중요한 핵심입니다.

어떤 목적이나 요구 사항을 가지고 프로그래밍하는지는 알 수 없어 부정확한 답변이 될 수 있는 점을 먼저 말씀드립니다.

저라면 말씀하신 상황에서 동시성 처리를 보장하는 ConcurrentQueue를 이용해서 백그라운드 스레드는 온전히 자신이 처리할 입력만 받고, UI에 표시할 최종 결과는 volatile 키워드를 이용해서 잠금 없이 즉시 데이터를 읽거나 쓸 수 있도록 구성하는 방식을 사용할 것 같습니다.

4개의 좋아요

그리드 컨트롤은 어떤걸 쓰시나요? 아마도 종목 목록을 표현하고 실시간 시세를 수신 받아서 가격 등의 정보가 변경되었을 때 강조 표시를 하는것 같은데요, 먼저 간단하게 실행되는 샘플 코드를 만들어서 동일한 문제가 발생하시면 그 샘플 프로젝트를 공유 주시는 건 어떠세요?

정보 수신은 그냥 임의로 랜덤값을 넣어주면 될 것 같습니다. 다만 발생 조건 (1초당 발생횟수 등)은 비슷하게 구성하시고요.

참고로

```csharp
코드 삽입
```

하시면 좀 더 보기 깔끔해집니다.

2개의 좋아요

일단 매번 이벤트 마다
스레드를 생성해서 처리하는 것 자체가 상당한 비용이 발생되고 안좋은 것 같습니다.
거기다 스레드풀 사용도 아니구요

큐 같은 자료구조를 사용해서 하나의 작업 스레드로 일 처리를 하고
UI처리는 이벤트 등 통보를 받을 수 있는 디자인패턴을 설계해서 처리 하는 것이 좋을 것 같습니다.

또 UI에 보여지는 셀 이 많아서 한 화면에 보여지는 것이 아니라면 UI가상화 같은 기법을 찾아보셔서
화면에 보여지지 않은 부분은 처리하지 않도록 하는 것도 하나의 방법 입니다.

3개의 좋아요

답변 달아 주신 분들 감사 합니다.

우선 알려주신 큐 사용해서 해보는 방법을 찾아 보겠습니다.

아울러 해당 프로그램은 위에 분이 이야기 하신 것처럼 주식 관련 프로그램 입니다.

거래량 및 현재 가격을 API 로 받아 와서 그리드 Cell 에 입력 해주고

사용자 에게 알람 형태로 표시해 주기 위해 그리드 Cell 을 깜빡 거리게 만들어 주는

기능 입니다.

큐 방법을 사용해서 진행 해보겠습니다. 감사합니다.

2개의 좋아요

스레드 문제가 아니라 증권 API마다 정해진 초당 최대 호출 가능 횟수나 호출 간격(ms) 때문에 그럴겁니다. 즉, 1초에 10개의 호출을 했으면 먼저 호출한것부터 일정 간격을 두고 순서대로 응답을 하다보니, 이로인해 스레드가 지연되는것처럼 보일겁니다. 증권사마다 다르니까 해당 api 메뉴얼을 확인해보세요.
그리고, 윈폼에서는 증권사 프로그램처럼 자연스러운 ui 변경이 불가능합니다. 특히 컨트롤이 많을수록, 초당 한두번 변경하는것조차 밀리는 현상이 발생할 수 있는데, 자연스럽게 변경되는 ui를 표현하려면 C++ mfc로 만들어야될겁니다.

1개의 좋아요

여러분들의 도움으로 제가 원하던 결과 값을 얻었습니다.

[ConcurrentQueue Class (System.Collections.Concurrent) ]

이번 기회에 해당 클래스도 사용해 보고 좋은 공부가 되었습니다.

이런 개발 방법이 있다는것을 새롭게 알게 되어 너무 좋네요 ㅎㅎ

답변 주신 모든 분들 도움 감사드립니다.

2개의 좋아요

감사합니다!!!

1개의 좋아요