2009-09-24 2 views
0

주어진 컬렉션을 취하고 (Item 클래스의 Copy() 메서드가 제대로 정의 된) 항목을 복사하고, 데이터 항목은 두 가지 방법으로 클래스의 컬렉션 속성System.Timers.Timer Button_click보다 실행 시간이 10 분 이상 걸림

//populate Collection containing 40 items 
MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems); 

이 메소드가 불려로 채워진 컬렉션을 반환 : 요청과 System.Timers.Timer 개체의 '경과'이벤트를 통해.

이제 컬렉션의 40 개 항목에 거의 시간이 없습니다. button_click을 사용하거나 Timer 객체로 채워진 상태로 'ad hoc'으로 채워지는지 여부

이제 컬렉션의 크기를 늘리면 (1000 개의 항목이있는 다른 MyClass 개체) 프로세스가 예상보다 오래 걸릴 수 있지만 총 소요 시간은 약 6 초입니다. 괜찮습니다. 문제 없습니다. 초기화 (form_load)시 호출되거나 ad hoc (button_click)이라고 불리는 것은 약 6 초 동안 유지됩니다.

//populate Collection containing 1000 items 
MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems); 

그러나 정확한 코드 줄에서와 마찬가지로 동일한 메서드가 System.Timers.Timer 개체에 의해 호출됩니다. 그리고 경과 된 시간은 약 60 초 정도 걸립니다 (다른 실행시에는 56 초, 1 분 2 초, 1 분 10 초 ...). 동일한 프로세스에 대해 10 배!

System.Timers.Timer 객체가 Thread-pool에서 실행된다는 것을 알고 있습니다. 이것이 이유일까요? 스레드 풀의 우선 순위가 낮습니까, 아니면 대기열 전체가 시간을 차지합니까?

요약하면 더 나은 접근 방법은 무엇입니까? System.Windows.Forms.Timer를 사용하여 동일한 UI 스레드에서 실행 하시겠습니까?

감사합니다. 좋아

, 몇 가지 추가 정보 :

이 타이머 작업이 DLL 내에서 발생하는이 UI에 의해 호출된다. 메인 '핸들러'클래스 자체는 동일한 이벤트 핸들러를 모두 구독하는 타이머 객체의 컬렉션을 가지고 있습니다. 핸들러 클래스의 초기화는 다음과 같이 좀 작동합니다

UpdateIntervalTimer tmr = new UpdateIntervalTimer(indexPosition); 
tmr.Interval = MyClass.UpdateInterval * 60000; //Time in minutes 
tmr.Elapsed += new System.Timers.ElapsedEventHandler(tmr_Elapsed); 
this.listIntervalTimers.Add(tmr); 

나는 실제로 그것을 제공하기 위해 타이머 클래스를 상속 한 '인덱스에게'속성합니다 (EventArgs입니다뿐만 아니라 참조). 그런 식으로 하나의 이벤트 핸들러 (tmr_Elapsed) 내에서 타이머가있는 MyClass 객체를 식별하고 조치를 취할 수 있습니다.

핸들러 클래스는 이미 자체 스레드에서 실행 중이고 해당 작업에 대한 통찰력을 제공하는 사용자 정의 이벤트를 발생시킵니다. 이벤트는 UI에서 처리되고 (UI 컨트롤 및 기타 등등의 크로스 스레딩 액세스) 이벤트가 수신 된 시간과 함께 표시됩니다. 이는 '초기화'및 '임시'통화 모두에 해당됩니다 (이러한 경우에는 문제가 없습니다). - 결국,이 반응하는 UI를 유지하기 위해 의미하는 것

private void tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
{ 
      UpdateIntervalTimer tmr; 
      tmr = (UpdateIntervalTimer)sender; 

      MyClass c = listOfClasses[tmr.IndexPosition]; 

      observerEventArguments = new MyHandlerEventArgs("Timer is updating data for " + MyClass.ID); 
      MessagePosted(this, observerEventArguments); 

      try 
      { 
       //preparation related code 


       MyClass.CollectionOfItems = GetPopulatedCollection(MyClass.CollectionOfItems); 


       observerEventArguments = new ProfileObserverEventArgs(MyClass.ID + ": Data successfully updated"); 
       MessagePosted(this, observerEventArguments); 
      } 
      catch (Exception exUpdateData) 
      { 
       observerEventArguments = new MyHandlerEventArgs("There was an error updating the data for '" + MyClass.ID + "': " + exUpdateData.Message); 
       MessagePosted(this, observerEventArguments); 
      } 
     } 
+0

Elapsed 이벤트 핸들러 코드를 표시 하시겠습니까? –

+0

... 그리고 ti를 측정하는 방법에 대한 샘플을 제공해 주시겠습니까? 아마, 나? –

+1

좋아, 그래서 System.Windows.Forms.Timer를 사용하여 시도하고 그 차이는 그냥 쾅. 로 6 초로 되돌아갑니다. 이상하게도 System.Timers.Timer 객체가 실행 중이지만 Windows.Forms.Timer가 거의 작동하지 않을 때 내 CPU (Quad 코어 2.4)는 열심히 (40 %) 싸우고있었습니다. Forms.Timer 개체를 사용하여 계속 진행할 수 있습니다. 누구든지 CPU가 스레드 풀 (thread pool)에서 무엇 때문에 열심히 싸울 것인가에 대한 더 많은 아이디어를 가지고 있습니까? (즉, 풀을 만드는 것이 더 빠르지 않겠습니까?) – MoSlo

답변

1

글쎄, UI 스레드 이 더 높은 우선 순위를 가질 가능성이입니다 다음과 같이

실제 경과 이벤트가 보인다. 그러나 다른 일들이 계속 될 수 있습니다. 메서드가 스레드에 안전한 방식으로 UI에 액세스합니까? 그렇다면 분명히 스레드간에 마샬링 할 필요가 없을 때 더 빨라질 것입니다.

스레드 풀의 우선 순위를 높여 성능을 향상시킬 수는 있지만 그 외에는 더 많은 정보가 필요합니다.

I 조언 당신이 UI 스레드에서이 작업을 수행하지 않을 것이다 - 당신이 아직도있는 동안 6 초 UI를 걸려하는 것은 좋은 사용자 경험 :(

+0

Ok, 이것은 더 많은 조사가 필요하지만 System.Windows .Forms.Timer 지금은 괜찮습니다. 나는 프로세스 자체를 최적화하거나 우선 순위를 가지고 플레이해야 할 것이다. – MoSlo

0

있도록하지 않는 것은 간격 경과인가 타이머를 사용하여 여러 번 동일한 작업을 수행하는 이유는 UI 타이머가 system.timers.timer/system.threading.timer보다 빠르게 작동한다고 생각할 수있는 유일한 이유입니다. UI 타이머가 단일 스레드이므로

+0

귀하의 주장을 이해하지만 타이머는 15 분으로 설정되어 있습니다. 코드 내부에서 일어나는 일에 대한 출력을 제공하는 스레드 세이프리스트 박스가 있습니다. 완료된 작업은 다음 Tick (또는 Elapsed) 이벤트의 내부에 있습니다. 스레드 풀링 된 솔루션 대신 다중 스레드 솔루션을 살펴보아야 할 수도 있습니다. – MoSlo

관련 문제