执行线程挂起主UI

本文关键字:UI 挂起 线程 执行 | 更新日期: 2023-09-27 18:04:54

我在用户控件中创建了一个边框和一个标签。当窗口加载时,它从文本文件中读取要执行的任务列表,然后创建相同数量的用户控件并将其添加到堆栈面板。

<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并等待它关闭。但这次我的主界面挂起了。我希望主UI是启动的,故事板动画继续运行,表明任务仍在执行。任务完成后,我将在边界控件中放置一个叉号或勾号图像,指示操作是成功还是失败。为什么主UI挂起了?

执行线程挂起主UI

如果您希望在等待流程完成时保持UI活动,则应该订阅Exited事件。

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

和事件。

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