2010-01-20 2 views
1

.NET Compact Framework 응용 프로그램과 함께 Model-View-Presenter 설정이 있습니다. 표준 CF Form은 뷰 인터페이스를 구현하고 발표자의 생성자로 전달됩니다. 발표자는 view.Run();을 호출하여 양식을 표시합니다. 뷰는 그 다음에 Show()를 수행하고 발표자는 다시 데이터를로드하여 뷰에 채 웁니다..NET Compact Framework : 코드를 실행하기 전에 양식이 표시되도록하는 방법은 무엇입니까?

컨트롤이 발표자에게 반환되기 전에보기 자체가 표시되지 않는 문제가 있습니다. 발표자 코드가 데이터를로드하는 동안 몇 초 동안 차단되기 때문에 양식이 몇 초 동안 표시되지 않는 것이 효과적입니다. 발표자가 데이터로드를 시작하기 전에 자체적으로 Show()라고하는 양식이 있어도 양식이 표시되는 데이터로드가 완료 될 때까지는 아닙니다.

표준 Windows 환경에서 양식의 .Shown 이벤트를 사용할 수는 있지만 컴팩트 프레임 워크에는이 항목이 없으므로 해당 항목을 찾을 수 없습니다.

누군가 발표자의 코드를 시작하기 전에 내 양식을 완벽하게 볼 수있게하기 위해 짝수, 핀 보크 또는 다른 방법을 알고 있습니까? 이 시점에서, 나는 발표자에게 전화를 걸고 발표자에게 데이터로드를 시작하도록 알리는 양식을 좋아할 것입니다.

FYI - 우리는 복잡성과 리소스 사용을 줄이기 위해 멀티 스레딩을 피하려고합니다.

답변

1

중요한 문제는 발표자 데이터로드 방법이 완료되기 전에 양식이 페인트되지 않으며 Form_Load에서 this.Show()를 호출 한 경우이 후에 Application.DoEvents()를 직접 입력 해보십시오. .Show()를 사용하면 폼을 강제로 페인트 할 수 있습니다.

protected void Form_Load(blah blah blah) 
{ 
    this.Show(); 
    Application.DoEvents(); 

    ... data loading methods ... 
} 
+0

이처럼 어리석은 것으로서 Application.DoEvents() 정적 메서드는 추가 스레드를 사용할 필요없이 문제를 해결합니다. "UI가 멈추는 등의 원인이 될 수 있지만 이것이 필요한만큼 충분합니다. –

2

일반적인 규칙은 다음과 같습니다 는 UI 스레드

윈도우 (뿐만 아니라 윈도우 CE에서)의 UI 비동기 성격을 가지고에 차단 아무것도 할 수 없다. 즉, 대부분의 API 호출이 즉시 수행해야하는 작업을 수행하지는 않습니다. 대신 이벤트 대기열에 넣고 나중에 이벤트 펌프로 검색하는 일련의 이벤트를 생성합니다.이 이벤트 펌프는 본질적으로 UI 스레드에서 실행되는 무한 루프이며 하나씩 대기열에서 이벤트를 선택하고 처리합니다. .

위에서 결론을 내리면 특정 작업 (예 : 귀하의 경우에 윈도우 표시)을 요청한 후에도 UI 스레드에서 오랜 시간 일을 계속하면 이벤트 펌프가 이벤트를 선택할 수 없습니다 당신은 그것에 통제권을 돌려주지 않았기 때문에, 당신의 요청 된 행동은 완료 될 수 없습니다.

일반적인 접근 방식은 다음과 같습니다. 복잡한 데이터 변환 /로드/준비/모든 작업을 수행해야하는 경우 별도의 스레드에서 수행 한 다음 Control.BeginInvoke를 사용하여 UI 스레드에 대리자를 주입하고 해당 델리게이트 내부의 실제 UI 컨트롤.

멀티 스레딩이 가져 오는 "복잡성"에 대한 비합리적 인 두려움에도 불구하고 두려워 할 점은 거의 없습니다. 여기에 포인트를 설명하기 위해 약간의 예입니다 : 당신이 다른 솔루션 놀 수 있지만

public void ShowUI() 
{ 
    theForm = new MyForm(); 
    theForm.Show(); 

    // BeginInvoke() will take a new thread from the thread pool 
    // and invoke our delegate on that thread 
    new Action(PrepareData).BeginInvoke(null,null); 
} 

public void PrepareData() 
{ 
    // Prepare your data, do complex computation, etc. 

    // Control.BeginInvoke will put our delegate on the UI event queue 
    // to be retrieved and executed on the UI thread 
    theForm.BeginInvoke(new Action(PutDataInTheForm)); 
} 

public void PutDataInTheForm() 
{ 
    theForm.textBox1.Text = "data is ready!"; 
} 

는 일반적인 생각은 항상 동일하게 유지 : 당신은 UI 스레드에서 긴 아무것도 할 경우, 당신의 UI가 "정지"됩니다. 다시 그리기는 비동기 프로세스이기 때문에 화면에 새 UI 요소를 추가해도 자체가 다시 그려지지 않습니다.

따라서 복잡한 스레드와 긴 스레드는 별도의 스레드에서 수행해야하며 UI 스레드에서 빠른 작업을 보장하는 간단하고 작은 작업 만 수행해야합니다. 정말로 다른 대안은 없습니다.

희망이 도움이됩니다.

+0

저는 이것이 해결책이라는 것에 대해 낙관적이었습니다! 하지만 BeginInvoke는 NotSupportedException을 throw합니다. ".NET Compact Framework에서는 대리자를 비동기 적으로 호출 할 수 없습니다." : –

+1

.NET Compact Framework에서는 BeginInvoke를 지원하지 않지만 ThreadPool.QueueUserWorkItem을 사용하면 기본적으로 동일한 작업을 수행 할 수 있습니다. 더 멋지게 보이게하려면 스레드 풀 액세스를 확장 메서드 으로 래핑하십시오. public static IAsyncResult BeginInvoke (이 Func 함수), –

0

원하지 않는 경우 다른 스레드를 만들 필요가 없습니다 (몇 초가 어떻게 든 처리되어야 함). 활성화 된 이벤트를 사용할 수 있습니다. 폼이 활성화 될 때 실행되므로 폼을 확인하기 위해 폼의 로컬 부울이 필요하거나 폼이 처음으로 만들어지지 않았어야합니다. 또 다른 옵션은 양식 표시를 마치면 바로 이벤트 처리기의 연결을 끊는 것입니다.

관련 문제