2014-06-19 4 views
0

wpf 응용 프로그램에서 - UI가 버튼 클릭으로 고정되고 - 거대한 데이터 처리 중에 통화 중 표시기를 표시하는 방법?긴 프로세스가 실행되는 동안 사용중 표시기를 표시하는 방법은 무엇입니까?

나는 배경 작업자 프로세스를 시도했지만 그 예외를 던지고있다.

메시지에서 "호출 스레드가"당신의 UI 스레드가 아닌

...

샘플 코드 :

private void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle); 

     BackgroundWorker worker = sender as BackgroundWorker; 
     this.busyIndicator.Visibility = Visibility.Visible; 
     busyIndicator.IsBusy = true; 

     for (int k = 1; (k <= 10); k++) 
     { 
      if ((worker.CancellationPending == true)) 
      { 
       e.Cancel = true; 
       break; 
      } 
      else 
      { 
       int intAutomationID = 0; 
       int intAutomation_SS_ID = 0; 
       int intAS_ID = 0; 
       string strProcedureName = ""; 
       //busyIndicator.Visibility = Visibility.Visible; 
       try 
       { 

        // Insert entry into AUTOMATION_PROCESS table. 
        intAutomationID = Pkg_TargetsIdentifiers.InsertAutomationProcess(Convert.ToInt32(cmbIdentifier.SelectedValue), 
         Convert.ToInt32(cmbSourceData.SelectedValue), "InProgress", 0, "Insert"); 

        if (intAutomationID > 0) 
        { 
         for (int i = 0; i <= dgvProcessLists.Items.Count - 1; i++) 
         { 
          int j = 3; 
          strProcedureName = ""; 
          strProcedureName = (dgvProcessLists.Items[i] as DataRowView).Row.ItemArray[j].ToString(); 
          if (!string.IsNullOrEmpty(strProcedureName)) 
          { 

           //AS_ID 
           // InitializeMouseHandlersForVisual(dgvProcessLists); 
           intAS_ID = Convert.ToInt32((dgvProcessLists.Items[i] as DataRowView).Row.ItemArray[0].ToString()); 

           intAutomation_SS_ID = Pkg_TargetsIdentifiers.InsertAutomationStepsStatus(intAS_ID, intAutomationID, 
           "Inprogress", 0, "Insert"); 

           bool boolStatus = Pkg_TargetsIdentifiers.CallActionProcess(strProcedureName, intAutomationID); 
           if (boolStatus == true) 
           { 
            //var selectedRow = DataProcessing.Class1.GetSelectedRow(this.dgvProcessLists); 
            //var columnCell = DataProcessing.Class1.GetRow(this.dgvProcessLists,0); 


            intAutomation_SS_ID = Pkg_TargetsIdentifiers.InsertAutomationStepsStatus(intAS_ID, intAutomationID, 
            "Completed", intAutomation_SS_ID, "Update"); 
            intAS_ID = 0; 
            strProcedureName = ""; 
            DataRowView row = (dgvProcessLists.Items[i] as DataRowView); 
            if (row != null) 
            { 
             if (row.DataView.Table.Columns.Contains("Status")) 
             { 
              Type type = row["Status"].GetType(); 
              string status = row["Status"] == System.DBNull.Value ? null : (string)row["Status"]; 


              if (boolStatus == true) 
              { 
               Uri uri = new Uri("pack://application:,,,/Images/green.jpg"); 
               BitmapImage source = new BitmapImage(uri); 


              } 
              if (boolStatus == false) 
              { 
               Uri uri = new Uri("pack://application:,,,/Images/red.jpg"); 
               BitmapImage source = new BitmapImage(uri); 

              } 
             } 
            } 
            continue; 
           } 
           else 
           { 
            break; 
           } 
          } 
         } 
         intAutomationID = Pkg_TargetsIdentifiers.InsertAutomationProcess(Convert.ToInt32(cmbIdentifier.SelectedValue), 
         Convert.ToInt32(cmbSourceData.SelectedValue), "Completed", intAutomationID, "Update"); 

        } 

        // Perform a time consuming operation and report progress. 
        System.Threading.Thread.Sleep(500); 
        worker.ReportProgress((k * 10)); 
       } 
       catch (Exception ex) 
       { 
        throw ex; 
       } 
       finally 
       { } 
      } 
     } 
    } 
    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle); 

     if ((e.Cancelled == true)) 
     { 
      this.busyIndicator.Visibility = Visibility.Hidden; 
      busyIndicator.IsBusy = false; 
     } 

     else if (!(e.Error == null)) 
     { 
      this.busyIndicator.Visibility = Visibility.Hidden; 
      busyIndicator.IsBusy = false; 
     } 

     else 
     { 
      this.busyIndicator.Visibility = Visibility.Hidden; 
      busyIndicator.IsBusy = false; 
     } 
    } 
    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     this.busyIndicator.Visibility = Visibility.Visible; 
     busyIndicator.IsBusy = true; 
    } 

    /// <summary> 
    /// btnStartProcess_Click 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void btnStartProcess_Click(object sender, RoutedEventArgs e) 
    { 
     try 
     { 
     if (bw.IsBusy != true) 
     { 
      bw.RunWorkerAsync(); 
     } 

      //worker.RunWorkerAsync(); 
     // //}; 

     // //worker.RunWorkerCompleted += (o, ea) => 
     // //{ 
     // // busyIndicator.Visibility = Visibility.Hidden; 
     // // busyIndicator.IsBusy = false; 
     // //}; 

     // //worker.RunWorkerAsync(); 
     // //}; 
     // //worker.RunWorkerAsync(); 

     //bw.RunWorkerCompleted += (o, ea) => 
     //{ 
     // busyIndicator.IsBusy = false; 
     // busyIndicator.Visibility = Visibility.Hidden; 
     //}; 
     //busyIndicator.IsBusy = true; 
     //busyIndicator.Visibility = Visibility.Visible; 
     //bw.RunWorkerAsync(); 
     } 
     catch (Exception ex) 
     { 

      throw ex; 
     } 
    } 

이 필요한 작업을 수행하십시오 ..

감사와 안부, 비제이 Babu

+0

이 몇 가지 코드를 표시하고 문제 – Nitin

+0

답변

-1

가 {

 System.Threading.ThreadStart start = delegate() 
     { 
      CallAutomationProcess(); 
      //done doing work, send result to the UI thread 
      Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, 
       new Action(changest)); 

     }; 
     this.busyIndicator.IsBusy = true; 
     this.busyIndicator.Visibility = Visibility.Visible; 

     new System.Threading.Thread(start).Start(); 
+0

-1 사용이 끝난 솔루션 일 수 있지만 매우 좋지 않은 솔루션입니다. 'System.Threading.Thread' 클래스는'Task' 클래스와 .NET 4.5에서'await'와'async' 키워드로 대체되어 .NET에서 더 이상 사용되지 않습니다. – Sheridan

+0

나는 당신에 동의합니다. 많은 .NET 4.5 기능이 Tasks로 변경되었으며 BackgroundWorker는 현재 쓸모 없게되었습니다. 하지만 일부 프로젝트에서는 .NET 4.0에 대한 작업을 해왔으므로 이러한 클래스/메서드를 사용했습니다. –

+0

@Sheridan이 지적한대로 Task 클래스는 .Net 4에서 사용할 수 있습니다. – Dzyann

-1

시험해보기 :

Dispatcher.Invoke(() => { busyIndicator.Visibility = Visibility.Visible; }); 
+0

왜 downvote? 이 코드는 작동하며 배경 작업자와 UI를 업데이트 할 때 많은 장소 (여기에 있습니다)를 보았습니다 ... – Eirik

+0

-1 죄송합니다, 나는 일반적으로 코멘트를 남깁니다. 나는 당신이 대답해야 할 때 또는 어디서 전화해야하는지에 대한 문맥을 제공하지 않았기 때문에 답변을 썼다. 또한 Dispatcher를 호출 할 필요도 없습니다.'Visible'을'Visible'으로 설정하려면'Invoke'를 실행해야합니다. 왜냐하면 실행은 여전히 ​​UI 스레드에서 진행되는 동안 * BackgroundWorker를 시작하기 전에 수행되어야하기 때문입니다. 나는 당신의 전화가 'Dispatcher.Invoke'에 대한 질문 작성자의 전화처럼 무의미하지는 않으나 모두 똑같이 필요하지는 않습니다. – Sheridan

+0

설명 및 코드 제안에 감사드립니다. 주어진 코드를 편집했습니다 - 새 스레드를 시작하기 전에 UI 수정 작업을 수행하십시오 2. 새 스레드를 작성하십시오. 3. UI 스레드로 결과 보내기 ... –

0

먼저, BackgroundWorker 코드가 작동해야합니다. 이를 위해 명확하고 간결한 코드 예제를 제공하는 How to correctly implement a BackgroundWorker with ProgressBar updates? 질문에 대한 제 대답을 참조하십시오.

이제는 사용자가 BackgroundWorker을 올바르게 설정했다고 가정하고 통화 중 표시기로 이동할 수 있습니다. 첫째, 당신은 당신의 오류의 원인을 알고 있어야합니다 :

We cannot call any functions on any UI objects from any other thread than the UI thread

이 점을 염두에 베어링, 그것이 우리가 백그라운드 스레드에서 모든 통화 지표의 Visiblity을 설정할 수 없음을 의미합니다. 우리는 MSDN의 오피스 페이지에서 볼 수 있듯이

busyIndicator.Visibility = Visibility.Visible; 
busyIndicator.IsBusy = true; 
backgroundWorker.RunWorkerAsync(); 

:

You must be careful not to manipulate any user-interface objects in your DoWork event handler. Instead, communicate to the user interface through the ProgressChanged and RunWorkerCompleted events.

을이 기본적으로 우리가 처리 할 수 ​​있다는 것을 의미 그래서, 가장 쉬운 수정 프로그램은 BackgroundWorker을 시작 전에 Visibility.Visible로 설정하는 것입니다 이러한 이벤트는 UI 스레드에서 발생하므로 이러한 이벤트 핸들러에서 UI 요소에 액세스 할 수 있습니다. 따라서 장기 실행 프로세스가 완료되면 RunWorkerCompleted 이벤트가 호출됩니다. 이 이벤트를 처리하는 경우에, 당신은 관련 이벤트 처리기에서 바쁜 표시를 숨길 수는 UI 스레드에서 실행으로 Dispatcher.Invoke를 호출 할 필요가 없다,

private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    busyIndicator.Visibility = Visibility.Hidden; 
    busyIndicator.IsBusy = false; 
} 

을, 그리고 그것을 언급하는 것은 가치가 그에게 전화

Dispatcher.Invoke(new Action(() => { /*No action*/ }), DispatcherPriority.ContextIdle); 
관련 문제