2013-03-28 2 views
0

잠시 기다려주십시오 상자가 화면에 표시되는 동안 주 양식을 잠그려고하지만 작동하지 않습니다. 여기 내 딜레마가있다.C#에서는 어떻게 폼을 잠글 수 있습니까?

2 가지 형식이 있습니다. 사용자가 새로 고침 단추를 클릭하여 SQL Server 목록을로드하는 기본 폼과 목록을로드하는 동안 표시되는 잠시 기다려주십시오 폼. SQL Server 스레드는 C#을 사용하는 동안 기본적으로 별도의 스레드이며 SQL 요청을 처리하기 위해 주 스레드를 잠급니다.

배경 작업자를 추가 할 수 있지만 목록을 UI 컨트롤로 표시하도록 콤보 상자를 업데이트 할 수 없습니다. 만약 내가 처리기를 사용한다면, 잠깐 기다려주세요 상자에 대한 내 show_dialog()는 메인 폼을 잠그는 것을 멈출 것입니다.

주 스레드가 다시 활성화 된 후 왼쪽 클릭 대기열을 실행하지 않고도이 양식을 잠글 수 있습니까? 사용자가 대기하는 동안 실행해야하는 코드를 추가했습니다.

public void PullServers() 
    { 
     bool ServersFound = false; 
     foreach (string Value in SQL.LocateSqlInstances()) 
     { 
      this.cmbServer.Items.Add(Value); 
      ServersFound = true; 
     } 

     if (!ServersFound) 
     { 
      this.cmbServer.Items.Add(Strings.Lang("ddServerNoneFound")); 
      this.cmbServer.SelectedIndex = 0; 
     } 
     else 
     { 
      if (!s.empty(General.setting("SQLSERVER"))) 
      { 
       this.cmbServer.Text = General.setting("SQLSERVER"); 
      } 
      else 
      { 
       this.cmbServer.SelectedIndex = 0; 
      } 
     } 

     this.picRefreshServers.Image = Properties.Resources.Refresh; 
    } 

    public static Array LocateSqlInstances() 
    { 
     using (DataTable sqlSources = System.Data.Sql.SqlDataSourceEnumerator.Instance.GetDataSources()) 
     { 
      string Servers = null; 
      foreach (DataRow source in sqlSources.Rows) 
      { 
       string instanceName = source["InstanceName"].ToString(); 

       if (!s.empty(instanceName)) 
       { 
        Servers += source["ServerName"].ToString() + "\\" + instanceName + "[[SERVBREAK]]"; 
       } 
      } 

      string[] ServersList = Servers.Split(new string[] { "[[SERVBREAK]]" }, StringSplitOptions.RemoveEmptyEntries); 
      return ServersList; 
     } 
    } 
+1

'양식 잠금'이란 무엇입니까? 이러한 기능이 실행되는 동안 사용자가 컨트롤을 클릭하지 못하게합니까? – IAbstract

+1

임포 "기다려주세요"상자를 대화 상자로 열어야합니다. 그 밑에있는 양식은 "잠겨"있습니다. –

답변

0

나는 당신이 BackgroundWorker로 올바른 길을 가고 있다고 생각합니다. 나는 나를 위해 잘 작동하는 다음 패턴을 발견했다.

기본 양식에 다음 단계를 수행해야합니다.

  1. 장기 실행 작업을 수행하려면 BackgroundWorker를 만듭니다.
  2. BackgroundWorker를 시작하십시오.
  3. 대기중인 양식을 모달 대화 상자로 표시합니다. 이 UI 스레드에서 실행되지 않기 때문에 아시다시피
// Step 1: 
BackgroundWorker bg = new BackgroundWorker() 
bg.DoWork += new DoWorkEventHandler(bg_DoWork); 
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted); 

// Step 2: 
bg.RunWorkerAsync(); 

// Step 3: 
waitingForm = new WaitingForm(); 
waitingForm.ShowDialog(); 

, 당신은 bg_DoWork 핸들러에서 UI를 업데이트 할 수 없습니다. 따라서 여기에 필요한 데이터를 가져 와서 e.Result 매개 변수를 사용하여 bg_RunWorkerCompleted 처리기로 전달하십시오.

private void bg_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Array servers = SQL.LocateSqlInstances(); 
    e.Result = servers; 
} 

은 여기 컨트롤을 업데이트하는 것이 안전하므로 UI ​​스레드에 bg_RunWorkerCompleted 실행됩니다. 여기서 대기중인 양식을 닫은 다음 UI를 업데이트해야합니다.

private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    // Close the Waiting form. 
    waitingForm.Close(); 

    // Retrieve the result of bg_DoWork(). 
    Array servers = e.Result as Array; 

    bool ServersFound = false; 
    foreach (string Value in servers) 
    { 
     this.cmbServer.Items.Add(Value); 
     ServersFound = true; 
    } 

    if (!ServersFound) 
    { 
     this.cmbServer.Items.Add(Strings.Lang("ddServerNoneFound")); 
     this.cmbServer.SelectedIndex = 0; 
    } 
    else 
    { 
     if (!s.empty(General.setting("SQLSERVER"))) 
     { 
      this.cmbServer.Text = General.setting("SQLSERVER"); 
     } 
     else 
     { 
      this.cmbServer.SelectedIndex = 0; 
     } 
    } 

    this.picRefreshServers.Image = Properties.Resources.Refresh; 
} 
+0

아주 좋습니다. 그것은 잘 돌아갔다. 고맙습니다. =) –

관련 문제