2009-04-30 4 views
1

마우스 휠을 통해 패닝, 확대/축소 및 확대/축소 할 수있는 상자를 그린 상사를위한 이미지보기 컨트롤을 만들었습니다. 컨트롤은 매우 큰 이미지 파일 (즉, 각면에 수천 픽셀)을 지원해야합니다.스레드 이미지 스케일링 하위 여전히 UI가 없습니다

모두 작동하지만 코드가 이미지의 크기를 조절할 때마다 컨트롤 UI가 응답하지 않게됩니다. 내 상사는 스레딩을 사용하여 UI에서 크기 조정 코드를 설정해야했습니다. 스케일링 코드는 이제 별도의 스레드에 있지만, 스케일링 코드가 실행되는 동안 UI는 여전히 허술합니다. 아무도 이것으로 나를 도울 수 있습니까 ??

아래는 스케일링 코드입니다. 이것이 나를 돕기에 충분하지 않다면 알려주고 필요한 코드를 올리십시오!

업데이트 : 여기에 전체 컨트롤 코드가 있습니다. link text

+1

이 메소드를 어떻게 호출합니까? 문제는이 함수가 아니라 비동기 적으로 실행하려고 시도하는 방식입니다. 호출 컨텍스트를 게시/설명하십시오. –

+0

스키, 내 대답에 최신 업데이트 코드를 시도하십시오. 또한 ScaleImageArguments와 img 인수 ByVal을 모두 전달합니다. 그것들은 ByRef를 통과해야합니다. 이것이 UI가 ScaleImage를 실행하는 동안 스레드가 차단하는 이유는 아닙니다. –

답변

0

GDI + API 내에 일부 전역 잠금이있는 것처럼 보입니다. 그들이 내 CPU의 두 코어를 활용할 수 있도록 테스트를 위해 내가 무한 루프 벤이 비어있는 경우 기능을

 
static void test_thread() 
{ 
    Bitmap bmp = new Bitmap(4000, 4000); 
    Graphics g = Graphics.FromImage(bmp); 
    Brush b = Brushes.Red ; 

    for (; ;) { 
     g.FillRectangle(b, 0, 0, bmp.Width, bmp.Height); 
    } 
} 

을 다음 사항에 따라 두 개의 스레드를 생성, CPU 사용률은 90 % 이상이었다. FillRectangle을 사용하면 사용률이 50 %로 약간 낮아져 한 스레드 만 시간에 실행할 수 있음을 나타냅니다.

따라서 스케일링이 진행되는 동안 GUI 스레드에서 수행하는 모든 GDI + 호출은 축척이 완료 될 때까지 차단 될 수 있습니다.

+0

당신이 정확합니다! 그래픽을 오랫동안 사용하는 빈 루프 및 스레딩이 의도 한대로 작동하는 스레드 함수에서 코드를 바꾸려고했습니다. 즉, 내 컨트롤이 그래픽 코드없이 빈 상자를 보여줍니다. 이제 질문은 어떻게 GDI + 차단을 우회 할 수 있습니까? 나 자신의 스케일링 함수를 써야 할까? – Ski

+0

pinvoke 메커니즘을 사용하여 이전 GDI를 사용해보십시오. 문제는 스케일링의 품질을 제어 할 수 없으며 다른 제한이있을 수 있다는 것입니다. 그 이외에 나는 당신이 당신의 스케일러를 쓰거나 기존의 스케일러를 찾아야한다고 믿습니다. – Komat

0

스케일링은 UI가 허둥지둥하고있는 모든 CPU를 사용하기 때문에 나는 의심 스럽습니다. 두 스레드는 아마 같은 우선 순위에 있습니다.

UI가 응답 할 수 있도록 크기 조정 스레드의 우선 순위를 낮추십시오.

Values for Thread Priority: 

Above Normal -> Gives thread higher priority 
Below Normal ->Gives thread lower priority 
Normal -> Gives thread normal priority 
Lowest -> Gives thread lowest priority 
Highest -> Gives thread highest priority 

so you would probably use: 

Thread1.Priority=System.Threading.ThreadPriority.BelowNormal 
+1

나는 그것이 어떻게 든 의심 스럽다. 나는 호출이 문제라고 생각한다. –

+0

위의 서브 루틴을 생성하고 시작하는 하위에서 BelowNormal에 우선 순위를 이미 설정했습니다. 우선 순위를 최저로 설정하면 아무런 차이가 없습니다. – Ski

+0

스키,이 메소드를 비동기 적으로 호출하는 방법에 대한 세부 정보를 제공해주십시오. 그러면 우리가 도울 수있을거야! –

0

대신 사용해보십시오.

Private Sub Worker(object o) 
    Dim args as ScaleImageArguments 
    args = CType(o, ScaleImageArguments) 
    ScaleImage(args) 
End Sub 

Private Sub RunScaleImageAsync(ByVal img As Image, ByVal scale As Double) 
    System.Threading.ThreadPool.QueueUserWorkItem(Worker, _ 
       New ScaleImageArguments(img.Clone, scale)) 
End Sub 

대안 - 비동기 패턴을 사용.

Private Delegate Sub ScaleImageDelegate(ByRef arg As ScaleImageArguments) 

Private Sub BeginScaleImage(ByRef img As Image, ByVal scale As Double) 
    Dim d As ScaleImageDelegate 
    d = New ScaleImageDelegate(AddressOf ScaleImage) 

    d.BeginInvoke(New ScaleImageArguments(img.Clone, scale), _ 
        New AsyncCallback(AddressOf EndScaleImage), d)   
End Sub 

Private Sub EndScaleImage(ar As IAsyncResult) 
    Dim d As ScaleImageDelegate 
    d = CType(ar.AsyncState, ScaleImageDelegate) 
    d.EndInvoke(ar) 
End Sub 

은 그럼 그냥 비동기 적으로 실행하는 BeginScaleImage를 호출합니다.

수정 - 위의 수정 사항을 참조하십시오. EndScaleImage의 ar 인수는 ByRef 및 BeginScaleImage의 img param으로 선언되어야합니다. 그들이 ByVal을 통과해야하는 이유는 없습니다!

+0

그냥 시도했지만 불행히도 차이는 없었습니다. – Ski

+0

두 번째 옵션도 시도해 보셨습니까? –

+0

두 번째 옵션을 시도했습니다. BeginScaleImage의 ByVal로 사용 된 img에서는 아무런 차이가 없었습니다. ByRef로 img를 사용하면 이미지가로드되는 동안 코드가 무한 루프에 걸리게됩니다. – Ski

0

ImageScaled()가 이미지를 UI로 다시 표시하는 방법은 무엇입니까?

+0

컨트롤에는 이미지의 배율 (Double)을 키로 사용하는 ScaledImageHash라는 이미지 사전이 있습니다. 컨트롤의 Paint 서브는 현재 이미지 스케일에 해당하는 ScaledImageHash의 이미지를 칠합니다. 사전을 사용하면 1) 나중에 사용하기 위해 이전에 크기 조정 된 이미지를 캐싱 할 수 있으며 더 중요한 것은 2) 사용자가 마우스 휠로 확대 할 때 잠재적 인 미래의 크기에 따라 이미지를 선점 할 수있는 기능을 제공합니다. 이 방법이 효과적이지만 이미지를 확대 할 때마다 컨트롤이 이미지를 다시 선명하게 비율 조정하고 UI가 느려집니다. – Ski

+1

페인트가 기다릴 수 있습니까? 당신은 괜찮 았지만, 스케일링이 일어나기를 기다리는 동안 UI가 표시되는 것은 무엇입니까? 스케일링이 완료 될 때까지 페인트 스레드에서 대기합니까? 아니면 스케일링이 끝날 때까지 페인트가 돌아 오지 않습니까? 처음이라면 다른 스레드에서 수행하더라도 여전히 "직렬"이므로 스레딩은 아무 것도 얻지 못합니다. 두 번째는 당신의 콜백이 그 다음 그것을 칠하기를 요구합니다. –

+0

@ 케빈 당신이 옳을 수도 있습니다. 나는 그가 작업이 완료되었을 때를 알기 위해 ImageScaled 이벤트를 사용하고 있다고 생각했습니다 - 시나리오가 그의 스레딩이 예상 된 결과를 산출하지 못하는 이유를 설명 할지라도. –

관련 문제