2012-05-16 9 views
2

UDP 브로드 캐스트의 일부 패킷을 처리하고 SQL 데이터베이스에 결과를 기록해야하는 앱이 있습니다. 간격 동안 들어오는 패킷의 속도가 상당히 높아지고 느린 데이터베이스 쓰기 때문에 기본 버퍼가 8MB로 오버플로된다는 것을 알았습니다.단일 스레드로 작업 마샬링하는 방법 C#

이 문제를 해결하기 위해 DB 쓰기, 및/또는 다른 순차적으로 작동하는 스레드에 기록하는 마샬링 중 일부를 캐시하는 두 가지 옵션이 있습니다. (db 쓰기 순서는 보존되어야합니다).

제 질문은 C#의 내장 구조/기능을 사용하여 가장 효과적으로 작업을 마샬링하는 방법입니다.

그냥 동기화 된 큐가 있어야하며 위임 작업 항목을 이벤트 루프에 넣고 단일 스레드 서비스를해야합니까?

+2

수신 된 각 패킷에 대해 하나의 트랜잭션을 처리하지 않도록 DB 쓰기를 집계해야합니다. 그렇지 않으면 미디어의 회전 속도로 인해 초당 약 30 건의 트랜잭션으로 클램핑됩니다. –

+2

여기에 꽤 기본적인 데이터 흐름 문제가 있습니다. 스레딩은 거의 실제 CPU 사이클을 소모하지 않으므로 마술 수정이 될 수 없습니다. UDP 대신에 TCP를 사용하는 것은 간단한 수정 일 것입니다. 또는 소방 호스가 당신이 따라 잡을 수있을만큼 충분히 오랫동안 꺼져 있다고 가정 할 때, 로컬 디스크에 쓰는 것을 포함하여 더 큰 버퍼. –

+0

데이비드와 한스와 100 % 동의합니다. (오늘 나에게 무슨 문제가 있습니까?) 일괄 업데이트 및/또는 저장 프로 시저로 DB 트랜잭션을 수정하면 DB 성능이 향상되고 데이터를 따라갈 수 있습니다. 그렇지 않다면 어떻게 든 흐름 제어를 적용해야합니다. UDP 방송에는 흐름 제어를위한 조항이 전혀 없으며 다른 방송 수신기는 데이터가 느려지 길 원치 않을 수도 있지만 많은 선택의 여지가 없다는 점에 감사드립니다. DB를 SSD에 넣을 수 있습니까? –

답변

2

가장 쉬운 방법은 UDP 읽기를위한 별도의 스레드를 만드는 것입니다.

스레드는 패키지를 받아서 BlockingCollection에 넣습니다. 는

BlockingCollection<Packet> _packets = new BlockingCollection<Packet>(); 
... 

while (true) { 
    var packet = udp.GetNextPacket(); 
    _packets.Add(packet); 
} 

이 읽기 ​​스레드가 사용 중이 어서 어떤 패키지를 놓치지 마세요 보장합니다 (당신이 그렇게이 될 것입니다 의사를 패킷 독서를 할 방법을 알고하지 마십시오).

그런 다음 현재 코드와 동일한 작업을 수행하지만 대신에 blockingcollection에서 읽는 작업자 스레드를 만듭니다.

while (true) { 
    var nextPacket = _packets.Take(); 
    ... 
} 

패키지가 독립적 인 경우 (UDP를 사용하고 있어야하므로) 여러 작업자 스레드가 실행될 수 있습니다.

1

.Net 4를 사용하는 경우 Tasks and TaskSchedulers을 사용하면 도움이됩니다. MSDN에서 LimitedConcurrencyLevelTaskScheduler을 찾을 수 있습니다. 동시성 레벨이 1 인 작업 인스턴스와 작업 할 때마다 작업을 작성하고 해당 스케줄러로 작업을 예약하십시오.

관련 문제