2009-05-19 6 views
1

BackgroundWorker를 사용하여 일부 양식의 불투명도 애니메이션을 만들었습니다.C#에서 BackgroundWorker로 폼 불투명도 애니메이션

이 접근법에는 단지 하나의 작은 문제 만 있지만 문제가 어디인지는 이해할 수 없습니다. 애니메이션 속도는 구성 가능하며 속도 값이 매우 높더라도 애니메이션이 때로는 매우 이상하게 느려지는 경우가 있습니다 ...

"느리게 움직이는 애니메이션"은 말 못하는 것입니다. 애니메이션은 실제로 매우 부드럽습니다. 전체 애니메이션을 수행하는 데 더 많은 시간이 걸립니다 (0 %에서 100 % 또는 부사). 이것은 때때로 발생합니다. 컴퓨터가 다른 다소 집중적 인 배경 작업을 수행 할 때 발생하는 것으로 보입니다 (확실하지 않은 것 같습니다).

물론 수정해야하지만 어쨌든이 코드를 향상 시키거나 다르게 또는 더 잘 수행 할 수 있는지 알고 싶습니다.

private const int TOGGLE_EFFECT_SPEED = 10; 

private void blendWorker_DoWork(object sender, DoWorkEventArgs e) { 
    bool blendIn = (bool)e.Argument; 

    // Loop through all opacity values 
    for(double value = 1; value <= 100; value += 1) { 
     // Report the current progress on the worker 
     blendWorker.ReportProgress(0, blendIn ? value : 100 - value); 

     // Suspends the current thread by the specified blend speed 
     System.Threading.Thread.Sleep(11 - TOGGLE_EFFECT_SPEED); 
    } 

    // Set the worker result as the inverse tag value 
    e.Result = !blendIn; 
} 

private void blendWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { 
    double opValue = (double)e.UserState; 

    // Show and repaint the whole main notes window? 
    if(opValue == 1.0) { 
     Show(); 
     Invalidate(true); 
    } 

    // Set the main notes window opacity value 
    Opacity = (double)e.UserState/100; 
} 

private void blendWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { 
    bool tagFlag = (bool)e.Result; 

    // Hide the main notes window? 
    if(tagFlag) { 
     Hide(); 
    } 

    // Set the main notes window tag value 
    Tag = tagFlag; 
} 

/* 
    THE FOLLOWING METHOD IS PART OF A DIFFERENT CLASS. 
    ACTUALLY, IT'S THE "PROGRAM" CLASS WHERE MAIN() 
    IS LOCATED. THIS METHOD IS CALLED TO SHOW/HIDE 
    THE MAIN APPLICATION FORM WITH AN OPACITY ANIMATION 
*/ 
internal static void ToggleNotesWindow() { 
    // Get the tag value converted to boolean type 
    bool tagFlag = Convert.ToBoolean(NotesWindow.Tag, CultureInfo.InvariantCulture); 

    // Bring the main notes window to front? 
    if(tagFlag) Program.NotesWindow.BringToFront(); 

    // Run the blend effect if it's not already running 
    if(!NotesWindow.blendWorker.IsBusy) { 
     NotesWindow.blendWorker.RunWorkerAsync(tagFlag); 
    } 

    // Activate and focus the main notes window? 
    if(tagFlag) Program.NotesWindow.Activate(); 
} 

답변

1

양식의 불투명도를 변경할 때마다 Windows는 그 아래에있는 모든 창을 다시 그려야하고, 창 자체가 불투명도를 적용해야합니다 (Vista는 훨씬 빠르고 버퍼링을 수행합니다). 1 ... 100의 각 불투명도 상태를 단계별로 진행하고 있으므로이 프로세스는 100 번 완료해야합니다. 때로는 창이나 창을 다시 그리는 것이 느려지기도합니다.

값이> 0 인 Thread.Sleep 메서드는 전달 된 값에 관계없이 0 ~ 10ms 사이에 잠자기 상태가됩니다. Windows의 스레드 스케줄러 타이머 해결은 약 10ms입니다 (Vista 및 기타 OS가 변경되어 최적화되지 않으므로 정확하지 않습니다). 따라서 이보다 작은 시간 조각을 예약 할 수는 없습니다. 100x10ms + 실제로 렌더링 할 시간은 페이드 인/아웃하는 데 2 ​​초 정도 걸릴 수 있습니다.

속도를 높이려면 다시 그리기 횟수를 줄이는 것이 좋습니다. 불투명도 +1, 단계 +5, +10 등으로 +1하는 것이 아니라 필요한 총 다시 그리기 횟수가 줄어들고 대신 100ms 내에 양식이 희미 해집니다.

+0

나는 그것이 틀린 이유라고 생각하지 않습니다. 나는 확실히 TOGGLE_EFFECT_SPEED = 1 (sleep (10))과 TOGGLE_EFFECT_SPEED = 10 (sleep (1))). 그리고 나는 또한이 두 가지의 차이가 1과 10 사이의 값으로 나타남을 느낍니다. 그리고 속도 값이 중요하지 않기 때문에 "느리게"의미하는 것을 얻지 못했다고 생각합니다. 문제는 속도없이 발생합니다 가치 변화. –

+0

스레드 스케줄러는 대부분의 상황에서 10ms 미만 동안 절전 모드를 유지하지 않으므로 속도 값 1과 10의 차이는 거의 볼 수 없습니다. 따라서 속도는 동일하게 나타납니다. 가장 큰 효과가있는 것은 윈도우와 윈도우를 렌더링하는 데 얼마나 천천히 걸리는지입니다. –

0

전반적으로 나는 적어도 첫눈에 변화를 보장 할 것을 많이 볼 수 없습니다 :

여기 내 코드입니다. 성능상의 병목 현상이 보이면 Ants Profiler 또는 유사한 코드 프로파일 링 도구를 사용하여 느린 섹션을 정확하게 찾아 볼 수 있습니다.

+0

그러나 "느린 섹션"이 없기 때문에 대부분의 경우 코드가 올바르게 작동합니다. 어떤 다른 시간은 종종 그런 것이 아니라 슬로우 모션으로 사라집니다 ... –

관련 문제