2009-03-10 5 views
0

this programming game을 참조하여 현재 작성 중입니다. (Robot에서 상속)하는 방법에서WPF : 애니메이션 완료 후 메서드 반환

public class MyRobot : Robot 
{ 
    public void Run(} 
    { 
     while (true) 
     { 
      Ahead(200); //moves the bot 200pixels 
      TurnLeft(90); //turns the bot by 90deg 
     } 
    } 
} 

, 시스템은 로봇 애니메이션됩니다

나는 그런 같은 것을 구성 될 것입니다 방법 Run있을 것이다 클래스 라이브러리 (DLL)이이 WPF를 사용하여 (BeginAnimation 또는 DispatcherTimer 사용).

이제 문제는 현재 애니메이션을 완성하기 전에 반환 할 방법이 없다는 것입니다 (즉, 다음 방법으로 넘어갑니다). 애니메이션이 함께 발생하기 때문에 결과가 무한합니다. 루프 (위의 것과 같음), 특히 좋지 않습니다.


내 질문은 애니메이션를 완료하기 전에 반환의 방법을 방지하는 가장 좋은 방법은 무엇인가, 입니까? 작업이 실행을 시작하고 (BeginAnimation를 사용하는 경우 Completed 이벤트를 사용하여) 애니메이션 콜백에서 false로 변경 될 때

나는 현재 true에 그 플래그 할 것을 Robot 클래스 (isActionRunning)에 bool 있습니다.

while (isActionRunning) 
{ 
    Thread.Sleep(200); //so that the thread sleeps for 200ms and then checks again if the animation is still running 
} 

이 방법은 애니메이션이 완료되기 전에 복귀 않도록이다 각 방법의 끝에

은 (BeginAnimation를 호출 한 후) I는 다음 루프를 두었다.

하지만 이것이 올바른 방법이 아니라고 생각합니다.

아무도 나를 이룰 수있는 가장 좋은 방법으로 인도 할 수 있습니까?

답변

3

Robot.Run 코드가 애니메이션을 수행하는 UI 스레드와 다른 스레드에서 실행되는 경우에만 사용할 수 있습니다.

Robot.Ahead 메소드 (예 :)에서 Dispatcher를 사용하십시오.빈 블록 (lock (this) {})이있는 로봇에 잠금을 추가하는 것보다 애니메이션을 시작하는 메서드를 호출하려면 (BeginInvoke가 아님) 호출하십시오. 애니메이션이 완성 처리기에서 애니메이션

시작 전에 애니메이션 호 Monitor.Enter (로봇)을 시작하는 방법에있어서

호출 Monitor.Leave (로봇)

는 결과가 될 것이다

time  robot thread   UI thread 
    |  ---------------  -------------- 
    |  call Invoke ---> 
    |        lock robot (Monitor.Enter) 
    |        begin animation 
    |  Invoke returns <--- return 
    |  lock(this)   (animation running) 
    |  (wait for lock 
    |  to become available) 
    | 
    |        Animation complete 
    |        release lock (Monitor.Exit) 
    |  (lock available, 
    |  continue running) 
    |  Release lock (exit lock block) 
    |  Return and start next 
    |  movement 
    \/ 
+0

훌륭합니다. while (isActionRunning) 루프 대신 제안한 것을 구현하기 위해 논리를 변경했습니다. –

+1

이것은 * 미친 *입니다. 하나의 스레드가 다른 스레드에게 현재 작업이 완료되었음을 알리는 신호를 기다리려면 잠금 신호를 생성하지 말고 ** 신호 **를 사용하십시오. 이미 프레임 워크에서이 작업을 수행하는 객체가 있습니다. 그냥 사용하십시오. http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx –

+0

@ Eric 왜 잠금 장치를 사용했는지 기억하지 못합니다 (1 년 전에 작성한 것입니다.) 좋은 이유 - 그러나 나는 신호가 아마도 올바른 해결책 일 수는 없다고 생각합니다. 내 경험에 의하면 뮤텍스 스타일의 잠금은 매우 강력하고 예측 가능하며 신호는 향후 모든 코드 변경을 어려운 경쟁 조건으로 바꾼다. (신호를 사용하는 C++ 멀티 스레딩 서버를 유지 관리해야했다. 동기화 - 신호에는 너무 많은 함정이있어 우습지 않다.) – Nir

0

나는 당신이 설명한 것과 비슷한 것을 할 것입니다. 최근 비동기 작업을 호출하는 곳에서 작업을 수행했으며 다른 작업을 호출하기 전에 모든 작업이 완료되기를 기다리고 싶었습니다. 현재 실행중인 모든 작업을 나타내는 컬렉션을 만들고 컬렉션에 항목을 직접 추가하는 대신 추가 및 제거하는 메서드를 만들었습니다. remove 메소드는 "콜렉션을 잠그고, 제공된 키를 제거하고, 비어있는 경우 다음 조작을 호출하는"논리를 가지고 있습니다. 이처럼 비슷한 메커니즘을 만들 수 있습니다.이 메커니즘은 응용 프로그램이나 윈도우 범위에서 실행되는 작업을 추적합니다. 컬렉션에 키를 추가하고이 키를 비동기 작업에 전달합니다. 비동기 작업이 완료되면 컬렉션을 잠그고 키를 제거합니다. 그런 다음 컬렉션에 키가 포함되어있는 동안 메서드가 반환되지 않도록하는 루프를 만들 수 있습니다 (시간 제한을 추가하기위한 선택 논리 또는 메서드가 반환 될 수 있고 영원히 차단되지 않도록 할 수있는 다른 추가 방법 사용).

과도 할 수도 있지만이 문제에 대한 경험은 제한적입니다. 내가 아는 한 .Net은 한두 줄의 코드로 작동하는이 문제에 대한 해결책을 가지고 있을지도 모른다.

5

신호 장치를 잠금 장치로 만드는 것은 냉소적입니다. 프레임 워크에 이미 존재하는 신호 장치를 사용하십시오. 이다

http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx

: 스레드 하나가 "헤이 실이,이 애니메이션을 시작하고 완료이 대기 핸들에 나를 신호."라고 쓰레드 1은 waithandle에서 기다립니다. 스레드 2는 애니메이션을 시작하고 완료 이벤트에서 신호를 보냅니다. 스레드 하나가 다시 깨어나서 "이봐, 스레드 2,이 다른 애니메이션 시작 ..."이라고 말합니다.

+0

안녕하세요 에릭, 당신이 권유 한 것처럼 노력했지만, 제게는 효과가 없습니다. 당신은이 스레드를 좀 봐 주시겠습니까 : http://stackoverflow.com/questions/3420901/synchronous-blocking-animations-in-wpf 대단히 감사합니다! 다른 사람이이 스레드의 문제에 대한 해결책을 찾았 을까요? –