2014-10-12 4 views
1

아래의 C# 프로그램을 재 설계하는 데 도움이되는 정보는 크게 감사하겠습니다. 1) TAP, 2) Bool이 false로 설정된 경우 종료되는 회 전자를 포함하는 코스 그레인 된 스레드 또는 3) 이러한 bool 대신 신호를 사용하는 동일한 스레드를 사용하여 멀티 스레딩을 구현하려고합니다. 나는이 사건을 분명히하기 위해 아래의 프로그램을 설명 할 것이다.디자인 : 작업 비동기 패턴 (대기/비동기가있는 TAP), 신호 대 다른 스레드 구조를 가진 스레드

프로그램

이 프로그램은 내가 언어와 C# (5.0) 더 나은 기능을 배울 수있는 재미있는 방법으로 개발하고 C#에서 게임 자동화 응용 프로그램입니다. 앱이 실행되는 동안 응답 성을 유지해야하는 UI가 있습니다.

UI의 특정 탭이 열리면 프로그램은 다른 클래스의 새 메서드에서 다양한 메모리 위치를 검색하고 빠르게 변경되는 값으로 UI의 레이블을 업데이트하는 "스캔"이라는 새 스레드를 시작합니다 UI의 SynchronizationContext를 사용합니다. 스캐닝 bool이 참 (일반적으로 프로그램의 전체 수명) 인 동안이 작업은 잠시 (스캐닝) 루프에서 계속됩니다.

사용자가이 탭에서 시작 단추를 클릭하면 프로그램은 다음을 수행하는 두 개의 새 스레드를 시작합니다. 스레드 "실행"은 특정 경로를 따라 문자를 이동합니다. Thread "Action"은 특정 버튼을 누르고 플레이어가 경로를 실행하는 동시에 작업을 수행합니다. 특정 시나리오가 발생하면 프로그램은 실행중인 스레드와 동작 스레드를 일시적으로 중지하고 메소드를 실행하며 완료되면 실행 및 조치로 돌아갑니다.

사용자가이 탭에서 중지 단추를 클릭하면 자동화가 중단되고 스레드가 종료됩니다.

과제는

는 이미 다양한 작업을 담당 각 스레드에서 연속 회 루프를 사용하여 작업 버전을 만들었습니다. 스피너는 잠시 사용합니다 (myBool). bool은 3 개의 스레드에 대해 스캐닝, 실행 및 동작 중 하나입니다.

스레드를 중지하려면 bool을 false로 설정하고 Thread.Join을 사용하여 스레드가 진행하기 전에 정상적으로 종료 될 때까지 기다립니다. 스레드는 언급 한 바와 같이 사용자가 중지 버튼을 클릭하거나 해당 기능의 일부로 프로그램에 의해 자동으로 중지 될 수 있습니다. 후자의 경우 스레드가 중지되고 조인 된 다음 나중에 다시 시작됩니다.

C# 5.0의 스레딩 및 새로운 비동기 프로그래밍 도구에 대한 많은 독서와 연구를 마친 후 현재 내가하고있는 방식이 매우 어색하고 전문가가 아닐 수도 있다는 것을 깨달았습니다. 이것은 많은 동기화/스레드 안전 문제를 만듭니다.이 모든 것의 목적은 C#에 대해 더 많은 것을 배우는 것이므로 대신 TAP을 사용하여 세밀한 비동기 프로그래밍 방식으로 변경해야하는지 여부를 결정하고 싶습니다. 비동기 및 적절한 때까지 기다립니다.

취소 토큰이있는 작업이 유용 할 수있는 경우와 비슷합니까? 쓰레드는 장기간 실행 된 작업 이후에 쓰레드 풀 (Task.Run)을 사용하면 쓰레드 풀 (over-subscription)에서 위생에 문제가 생길 우려가있었습니다. 비동기 프로그래밍이 여기에있어 좋지 않은 것처럼 보인다면, 내가 한 것처럼 쓰레드를 사용하는 대신 쓰레드를 시작하고 멈추기 위해 시그널링을 사용하는 것은 어떨까요?

모든 의견을 크게 높이 셨습니다.

+0

TPL DataStream 또는 ReactiveExtensions를 사용해 보셨습니까? 둘 다 동시 및/또는 비동기 데이터 파이프 라이닝 용으로 설계되었습니다. – Aron

답변

0

No. TPL은 새로운 스레드를 할당 할 때마다 성능이 저하되는 짧은 작업을 실행하도록 설계되었습니다.작업 대기열 및 작업 도용 (TPL 스레드는 다른 스레드에서 작업을 취할 수 있음)과 같은 아주 멋진 기능을 갖추고 있습니다. 당연히 더 오래 실행되는 작업을 할 수 있지만 그렇게 많은 이점을 얻지는 못할 것입니다. 반대로, 당신은 새로운 쓰레드를 할당하도록 TPL에게 강요한다.

그러나 실제로 사용해야 할 사항을 파악하기 위해 실제 구현에 대한 추가 정보가 필요하다는 점에서 일반적인 질문입니다. Scan 스레드의 경우 단일 스레드에서 실행해야한다는 것이 아주 분명합니다.

하지만 다른 사람들에게는 알기가 어렵습니다. 그들은 항상 또는 정기적으로 일합니까? 그들이 항상 작동한다면 별도의 스레드에 보관해야합니다.

스레드 동기화에 관해서는 다른 대안이 있습니다. ConcurrentQueue을 사용하여 그려야 할 모든 것을 큐에 넣을 수 있습니다. 그렇게하면 동기화가 필요하지 않습니다. UI 스레드가 대기열을 확인하고 그 안에 아무 것도 그려서는 안되지만 생산자는 작업을 계속할 수 있습니다.

사실, 이렇게하면 UI 드로잉과 관련이없는 것을 다른 스레드로 옮길 수 있습니다. 또한 응용 프로그램의 응답 성도 향상되어야합니다.

public void ActionRunnerThreadFunc() 
{ 
    _drawQueue.Enqueue(new SpaceShipRenderer(x, y)); 
} 

public void UIThreadFunc() 
{ 
    IItemRender item; 
    if (_drawQueue.TryDequeue(out item)) 
     item.Draw(drawContext); 
} 
+0

해답을 주셔서 감사합니다.이 앱은 실제로 게임이 아니라 오히려 게임 플레이를 자동화하는 도구입니다 (인간의 상호 작용없이 캐릭터를 움직이고 다양한 작업을 수행함). 나는 그들이 리턴 타입을 가질 수있을뿐만 아니라, 연속성 (await와 명시 적으로 또는'await' 키워드를 통해)을 첨부 할 수있는 가능성을 제공 할뿐만 아니라 태스크가 유용하다고 생각했다. 그래서 메모리 스캐너는 별도의 스레드에서 실행되어야하며 스캐너 bool 대신 ManualResetEvent.WaitOne을 사용할 수 있다고 생각합니다. (다음 댓글에서 계속) – Anders

+0

하지만 두 개의 다른 스레드에 대한 : 그들은 영원히 실행되지 않습니다. 내가하고 싶은 일은 나무를 자르는 것입니다. 따라서 한 스레드는 문자가 설정된 경로에서 돌아 다니게됩니다. 병렬로 실행되는 다른 스레드는 계속해서 단추를 클릭하여 나무를 찾습니다. 트리가 발견되면이 두 스레드는 일시적으로 중지되어야하며 treeChopping 메소드가 시작되어야합니다. 나무가 잘게 자르면, 선수는 나무를 찾는 길을 달리게해야합니다. 세 가지 작업이 여기에서 올바르게 작동하는 것처럼 느껴지십니까? – Anders

+0

나무 절단이 1 초 이내에 완료되면 나는 그것을 업무에서 돌릴 것이다. 그렇지 않으면 나는 그것을 분리 된 실에 보관할 것이다. – jgauffin