2010-08-13 9 views
4

스플래시 화면의 개념은 너무 복잡해야한다는 것을 알려주지는 않지만 전체 스플래시 화면이 그려지는 데 어려움을 겪고 있습니다.스플래시 화면 만들기

두 개의 System.Windows.Forms.Form : RealForm 및 SplashScreen이 있다고 가정 해 보겠습니다. RealForm은 초기 GUI를 포함합니다. RealForm의 로딩 프로세스 (즉, Load 이벤트의 이벤트 핸들러) 중에 RealForm은 데이터베이스에 대한 연결을 만든 다음 연결을 테스트합니다. 이 작업은 몇 초 정도 걸릴 수 있습니다, 그래서이 모든 작업을 수행하기 전에, 정말 같은 시작 화면을 던져보십시오 : 시작 화면이 부분적으로 만 그려됩니다 것을

private void RealForm_Load(object sender, EventArgs e) 
{ 
    SplashScreen splash = new SplashScreen(); 
    splash.Show(); 
    loadAndCheckDatabase(); 
    splash.Close(); 
} 

문제를 그래서 정말하지 않습니다 많은 스플래시 화면처럼 보입니다. 왜 그런가? 어떻게해야합니까?

보너스 포인트는 양식 작성, 사용 및 삭제시 발생하는 모든 일련의 이벤트에 대한 설명을 어디서 찾을 수 있는지 알고 있습니까? 위의 문제는 물건의 순서 나 양식 이벤트에 연결될 위치를 이해하지 못하기 때문일 수 있습니다.


UPDATE 닫기,하지만 확실히하지 : 좀 더 조언을 찾고. 여기에 현재 코드는 다음과 같습니다가 자동으로 내가 제어하지 않는 코드 true로 설정되어 있기 때문에

private SplashScreen splash = new SplashScreen(); 

private void RealForm_Load(object sender, EventArgs e) 
{ 

    splash.Show(); 

    BackgroundWorker worker = new BackgroundWorker(); 
    worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler 
     (worker_RunWorkerCompleted); 
    worker.RunWorkerAsync(); 
    this.Visible = false; 

} 

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    splash.Close(); 
    this.Visible = true; 
} 

void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    loadAndCheckDatabase(); 
} 

는 불행하게도, this.Visible = false는 아무것도하지 않습니다. 그래서이 문제를 해결하기 위해 this.Visible = false을 양식의 Shown 이벤트 처리기에 넣었습니다. 그러나 아마 추측 할 수 있듯이, 두 번째 분할에 대한 양식을 볼 수 있습니다 ... 그래서 이것은 정말 좋은 해결책은 아닙니다.

부하 처리기에있는 동안 작업자 스레드에서 대기 할 수있는 방법이 있습니까?

답변

9

스플래시 화면을 표시하고 동일한 스레드에서 데이터베이스를 확인하고 있습니다. 스레드는 한 번에 한 가지만 할 수 있습니다.

이 문제를 신속하고 저렴한 방법으로 해결하려면 loadAndCheckDatabase()을 주기적으로 Application.DoEvents()으로 호출해야합니다. 그러나 그것은 싼 수정입니다.

loadAndCheckDatabase()를 자체 스레드에서 실행하려면 BackgroundWorker이 좋은 간단한 방법입니다.

+2

이것은 분명 할 수 있지만 loadAndCheckDatabase 호출에는 UI 코드가 없으며 메시지 상자가 없거나 문제가 발생할 수 있습니다. –

+2

나는 Application.DoEvents()로 신경 쓰지 않고 그냥 BackgroundWorker를 사용한다. UI가 응답하는 동안 간단한 논리 단위를 실행하려면 BackgroundWorker를 사용하십시오. UI 스레드가 UI의 메시지 대기열에서 기다리고있는 모든 것을 실행하기를 원하는 경우 * 사용자가 마우스 클릭을 큐에 넣으면 다른 방식으로 임의의 논리를 수행하여 현재 작업을 방해 할 수 있습니다. 스레드로드가 실행되고 있지만 실제로는 하나만있는 경우 Application.DoEvents()를 사용하십시오. –

1

백그라운드 스레드에서 loadAndCheckDatabase를 호출하거나 스플래시 화면의 닫기를 이동하거나 스플래시 화면에서 타이머를 사용하여 간단히 닫으십시오. 백그라운드 스레드로 작업하면 모든 UI 기능이 중단없이 작동 할 수 있습니다.

1

스플래시 화면을 다른 스레드에서 실행해야 제대로 그릴 수 있습니다.

http://www.codeproject.com/KB/cs/prettygoodsplashscreen.aspx

+2

스플래시 화면은 UI 구성 요소이므로 실제로는 UI 스레드 (WinForms 앱의 기본 스레드)에서 실행해야합니다. loadAndCheckDatabase()는 작업자 스레드로 푸시되어야합니다. –

+0

UI 구성 요소는 백그라운드 스레드에서 실행될 수 없으며 실행해서도 안됩니다. 주 스레드에서만 실행해야합니다. – Russ

+0

바로 배경 스레드에 UI가 없으면 여러 스레드 호출 예외가 발생합니다. –

-2

당신은 닷넷 프레임 워크 4와 await를 명령을 사용할 수 있습니다

여기를 보라.작업이 당신이 클래스로로드해야 어떤 부하 양식을 열 응용 프로그램을 실행할 때로드가 끝나면 왜, 다음 주를 열

private void YourForm_Load(object sender, EventArgs e) 
    { 
     //call SplashScreen form 
     SplashScreen splash = new SplashScreen(); 
     splash.Show(); 
     Application.DoEvents(); 
     //Run your long task while splash screen is displayed i.e. loadAndCheckDatabase 
     Task processLongTask = loadAndCheckDatabase(); 
     //wait for the task to be completed 
     processLongTask.Wait(); 
     splash.Close(); 

     //... 
    } 
+2

위의 코드에는 아무런 이점이 없습니다. 주 스레드가 작업 대기 완료를 즉시 차단하기 때문입니다. 주 스레드에서 긴 작업을 수행하더라도 차이는 없습니다. – Mark

1

가 완료 될 때까지 5 양식이 표시되지 않습니다 양식을 작성하고 수업을 보내십시오. 또는 싱글 톤을 사용하여 모든 것을로드 할 수 있습니다. 되는 SplashScreen에서 다음

[STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new SplashScreen()); 
    } 

: 당신의 Program.cs에서

public SplashScreen() 
    { 
     InitializeComponent(); 
     LoadEverything(); 
     this.Visible = false; 
     MainForm mainForm = new MainForm(LoadedClass); 
     mainForm.ShowDialog(); 
     this.Close(); 
    } 

내가이를 업데이트해야합니다 : 여기

코드를 작동하고 (위의 단지 개념이다). 당신은 아마 군더더기로이 만든 멀티 스레드 아키텍처에 맞게 코드를 재 설계의 모든 지옥을 가고 싶지 않아 나 같은

public SplashScreen() 
    { 
     InitializeComponent(); 
     _currentDispatcher = Dispatcher.CurrentDispatcher; 

     // This is just for the example - start a background method here to call 
     // the LoadMainForm rather than the timer elapsed 
     System.Timers.Timer loadTimer = new System.Timers.Timer(2000); 
     loadTimer.Elapsed += LoadTimerElapsed; 
     loadTimer.Start(); 
    } 

    public void LoadMainForm() 
    { 
     // Do your loading here 
     MainForm mainForm = new MainForm(); 

     Visible = false; 
     mainForm.ShowDialog(); 
     System.Timers.Timer closeTimer = new System.Timers.Timer(200); 
     closeTimer.Elapsed += CloseTimerElapsed; 

     closeTimer.Start(); 
    } 

    private Dispatcher _currentDispatcher; 

    private void CloseTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     if (sender is System.Timers.Timer && sender != null) 
     { 
      (sender as System.Timers.Timer).Stop(); 
      (sender as System.Timers.Timer).Dispose(); 
     } 
     _currentDispatcher.BeginInvoke(new Action(() => Close())); 
    } 

    private void LoadTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     if (sender is System.Timers.Timer && sender != null) 
     { 
      (sender as System.Timers.Timer).Stop(); 
      (sender as System.Timers.Timer).Dispose(); 
     } 
     _currentDispatcher.BeginInvoke(new Action(() => LoadMainForm())); 
    } 
2

...

먼저 SpashScreen라는 새로운 양식을 작성 속성에서 BackgroundImage를 클릭하고 원하는 이미지를 가져옵니다. 또한 FormBorderStyle을 None으로 설정하면 x를 클릭하여 화면을 닫을 수 없습니다.

public Form1() 
    { 
     InitializeComponent(); 

     BackgroundWorker bw = new BackgroundWorker(); 
     bw.WorkerSupportsCancellation = true; 
     bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
     bw.RunWorkerAsync(); // start up your spashscreen thread 
     startMainForm();  // do all your time consuming stuff here 
     bw.CancelAsync();  // close your splashscreen thread 
    } 


    private void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker worker = sender as BackgroundWorker; 

     SplashScreen ss = new SplashScreen(); 
     ss.Show(); 

     while (!worker.CancellationPending) //just hangout and wait 
     { 
      Thread.Sleep(1000); 
     } 

     if (worker.CancellationPending) 
     { 
      ss.Close(); 
      e.Cancel = true; 
     } 

    } 

이것은 진행률 표시 줄이나 멋진 내용을 지원하지 않지만 조정할 수 있다고 확신합니다.

+0

샘플 주셔서 감사합니다. 마지막 'if'문은 불필요합니다. 위의 while 루프를 통해 worker.CancellationPending이 true가 아닌 한 코드는 거기에 도달하지 않습니다. –

관련 문제