2015-07-27 3 views
0

Я создал границу и метку в пользовательском элементе управления. Когда окно загружается, он считывает список задач, которые должны выполняться из текстового файла, а затем создает одинаковое количество пользовательских элементов управления и добавляет его в панель стека.Выполнение потока зависает главный пользовательский интерфейс

<UserControl x:Class="DiagnoseTool.TaskControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="30" d:DesignWidth="515" Height="40"> 
<UserControl.Resources> 
    <Storyboard x:Key="ShowBlink"> 
     <ColorAnimation From="White" To="LightGreen" Duration="0:0:0.5" Storyboard.TargetName="StatusRectangle" Storyboard.TargetProperty="Background.Color" AutoReverse="True" RepeatBehavior="Forever"/> 
     <!--ColorAnimation From="LightGreen" To="White" Duration="0:0:1" Storyboard.TargetName="StatusRectangle" Storyboard.TargetProperty="Background.Color"/--> 
    </Storyboard> 
</UserControl.Resources> 
<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="0.08*"></ColumnDefinition> 
     <ColumnDefinition></ColumnDefinition> 
    </Grid.ColumnDefinitions> 
    <Border x:Name="StatusRectangle" Margin="5" Grid.Column="0" Background="White" Width="20" Height="20" BorderThickness="1" BorderBrush="Black"></Border>  
    <Label x:Name="TaskNameLabel" Grid.Column="1" Margin="5" FontSize="12" Content="" FontFamily="Calibri"></Label> 
</Grid> 

Border имеет анимацию, которая меняет цвет фона с белого на зеленый, когда задача выполняется. Код позади taskcontrol содержит метод, который является:

/// <summary> 
    /// This function is used to perform some task 
    /// </summary> 
    /// <returns></returns> 
    public bool StartShowingProgress() 
    { 
     bool bRet = true; 
     try 
     { 
      sbdStatusDisplay = (Storyboard)FindResource("ShowBlink"); 
      sbdStatusDisplay.Begin(this, true); 
     } 
     catch (Exception ex) 
     { 
      bRet = false; 
     } 
     return bRet; 
    } 

Главное окно загружается обработчик событий:

private void MainWindowLoaded(object sender, RoutedEventArgs e) 
    { 
     for(int i=0;i<taskList.Count;i++) 
     { 
      Logger.WriteToLog(taskList[i].TASKNAME); 
      TaskControl objTaskControl = new TaskControl(taskList[i].TASKNAME); 
      TasksPanel.Children.Add(objTaskControl); 
     } 

     for (int i = 0; i < taskList.Count; i++) 
     { 
      (TasksPanel.Children[i] as TaskControl).StartShowingProgress(); 

      Thread th = new Thread(doSomeWork); 
      th.Start(i); 
      resetEvent.WaitOne(); 
     } 
    } 

Код Метод doSomeWork является:

 private void doSomeWork(object val) 
    { 
     int index = (int)val; 
     Utilities.StartProcess(taskList[index].TASKFILE, taskList[index].TASKARGUMENT, taskList[index].CHECKRETURNVALUE); 
     resetEvent.Set(); 
    } 

Код StartProcess является:

Process process = new Process(); 
      // Configure the process using the StartInfo properties. 
      process.StartInfo.FileName = fileToRun; 
      process.StartInfo.Arguments = arguments; 
      process.Start(); 
      //Check if we need to wait for the process to exit 
      if (waitForExit) 
      { 
       process.WaitForExit(); 
      } 

Когда я просто запускаю приложение без выполнения задачи, он отлично работает, а анимация раскадровки работает правильно. Но с помощью этого кода, в методе doSomeWork, он запускает notepad.exe и ждет его закрытия. Но на этот раз мой главный пользовательский интерфейс зависает. Я хочу, чтобы основной пользовательский интерфейс был включен и анимация раскадровки, чтобы продолжить выполнение, показывая, что задача все еще выполняется. Как только задача будет завершена, я затем поставлю крест или галочку внутри пограничного элемента управления, указав, была ли операция успешной или неудачной. Почему главный пользовательский интерфейс висит?

+0

'resetEvent.WaitOne()' блокирует поток пользовательского интерфейса до тех пор, пока не вызывается 'resetEvent.Set()'. – Clemens

ответ

1

Вы должны подписаться на событие Exited, если вы хотите, чтобы ваш пользовательский интерфейс активен, ожидая завершения процесса.

process.Exited += new EventHandler(OnProcessExited); 
process.Start(); 

И событие.

private void OnProcessExited(object sender, System.EventArgs e) 
{ 
    //TODO 
} 
+0

Но как основной поток пользовательского интерфейса ожидает завершения процесса? –

+2

@ ng-R Вам не нужен фоновый поток для запуска отдельного процесса. Просто запустите его из потока пользовательского интерфейса и обработайте событие Exited в потоке пользовательского интерфейса. – Clemens

Смежные вопросы