长操作功能是“阻塞” UI线程

时间:2019-07-10 07:09:36

标签: wpf asynchronous

我想在与UI线程不同的线程上运行Allocate()函数。现在的问题是,当分配运行时,我的“忙碌指示器”冻结了。

<Window
x:Class="WpfApp4_test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp4_test"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
x:Name="MainWindow1"
Title="MainWindow"
Width="800"
Height="450"
Closing="MainWindow1_Closing"
mc:Ignorable="d">   
<xctk:BusyIndicator x:Name="busyIndicator" IsBusy="True">
    <xctk:BusyIndicator.ProgressBarStyle>
        <Style TargetType="ProgressBar">
            <Setter Property="Background" Value="White" />
            <Setter Property="Foreground" Value="Cyan" />
            <Setter Property="Height" Value="15" />
            <Setter Property="IsIndeterminate" Value="True" />
        </Style>
    </xctk:BusyIndicator.ProgressBarStyle>
    <Grid x:Name="closing">
    </Grid>
</xctk:BusyIndicator>

C#代码如下:

 public partial class MainWindow : Window
{
    public MainWindow()
    {
        BusyScope.BusyScopeChanged += this.BusyScope_BusyScopeChanged;

        InitializeComponent();
        this.busyIndicator.IsBusy = false;
    }

    private bool? myFucnt()
    {

        if (true)
        {
            MessageBoxResult result = MessageBox.Show(
                this,
                $"There are unsaved changes. Would you like to save them before proceeding",
               "test",
                MessageBoxButton.YesNoCancel,
                MessageBoxImage.Warning,
                MessageBoxResult.Cancel,
                MessageBoxOptions.None);

            if (result == MessageBoxResult.Cancel)
            {
                return null;
            }

            if (result == MessageBoxResult.Yes)
            {

                if (!this.fct1())
                {
                    return false;
                }
            }
        }
        return true;
    }


    internal bool fct1()
    {
        try
        {                

            this.Dispatcher.Invoke(
            () =>
            {
                var message = "Save message";
                MessageBox.Show("1", message, MessageBoxButton.OK, MessageBoxImage.Error);
            });



            this.Allocate();              
            return true;
        }
        catch (Exception)
        {
            var message = "There was an error saving the file. Please check that the data is valid and try again.";               
            MessageBox.Show("1", message, MessageBoxButton.OK, MessageBoxImage.Error);
            return false;
        }
    }

    private void Allocate()
    {
        int size = 0;           

            for (int z = 0; z < 100; z++)
            {

                for (int i = 0; i < 1000000; i++)
                {
                    string value = i.ToString();
                    size += value.Length;
                }

            }            
        // Use bgWorker.ReportProgress(); to report the current progress      

    }

    private void MainWindow1_Closing(object sender, CancelEventArgs e)
    {

        bool? temp = null;
        BusyScope.IncrementBusyScope("closing");
        temp = this.myFucnt();

        if (temp != null)
        {
            Application.Current.Shutdown();
        }
        else
        {              
            e.Cancel = true;
        }            
        BusyScope.DecrementBusyScope();
    }
}

要执行它,只需关闭应用程序(按“ x”按钮)。忙碌指示器冻结,因为关闭应用程序时正在运行长时间操作。繁忙指示器一直正常工作,直到它“击中” Allocate()函数为止(因为此函数执行需要花费大量时间)。

我尝试这种方法: https://www.dotnetperls.com/async

picture

更新:

尝试了几次更改后,我完成了此修改

public partial class MainWindow : Window
{
    public MainWindow()
    {
        BusyScope.BusyScopeChanged += this.BusyScope_BusyScopeChanged;

        InitializeComponent();
        this.busyIndicator.IsBusy = false;
    }

    private bool? myFucntAsync()
    {

        if (true)
        {
            MessageBoxResult result = MessageBoxResult.Cancel;

            this.Dispatcher.Invoke(() =>
            {
                result = MessageBox.Show(
                this,
                $"There are unsaved changes. Would you like to save them before proceeding",
               "test",
                MessageBoxButton.YesNoCancel,
                MessageBoxImage.Warning,
                MessageBoxResult.Cancel,
                MessageBoxOptions.None);
            });

            if (result == MessageBoxResult.Cancel)
            {
                return null;
            }

            if (result == MessageBoxResult.No)
            {
                return false;
            }


            if (result == MessageBoxResult.Yes)
            {
                bool t = this.fct1();
                if (!t)
                {
                    return false;
                }
            }
        }
        return true;
    }


    private bool fct1()
    {
        try
        {
            this.Allocate();

            return true;
        }
        catch (Exception)
        {
            var message = "There was an error saving the file. Please check that the data is valid and try again.";
            MessageBox.Show("1", message, MessageBoxButton.OK, MessageBoxImage.Error);
            return false;
        }
    }

    private void Allocate()
    {
        int size = 0;

        for (int z = 0; z < 100; z++)
        {

            for (int i = 0; i < 100000; i++)
            {
                string value = i.ToString();
                size += value.Length;
            }

        }

    }

    private async void MainWindow1_Closing(object sender, CancelEventArgs e)
    {
        bool? temp = null;
        BusyScope.IncrementBusyScope("closing");

        var firstLongTask = Task.Run(() =>
        {
            temp = this.myFucntAsync();                

            if (temp != false)
            {

                MessageBox.Show("done");
                BusyScope.DecrementBusyScope();
                this.Dispatcher.Invoke(() =>
                {
                    Application.Current.Shutdown();
                });
                e.Cancel = false;
            }
            else
            {
                BusyScope.DecrementBusyScope();
                e.Cancel = true;
            }

            return true;
        });
        var secondLongTask = Task.Run(() =>
        {

            e.Cancel = true;
            return true;

        });            
        var result = await Task.WhenAll(firstLongTask, secondLongTask);           
    }        
}

通过这种方式,任务将执行this.myFucntAsync(),之后

            if (temp != false)
            {

                MessageBox.Show("done");
                BusyScope.DecrementBusyScope();
                this.Dispatcher.Invoke(() =>
                {
                    Application.Current.Shutdown();
                });
                e.Cancel = false;
            }
            else
            {
                BusyScope.DecrementBusyScope();
                e.Cancel = true;
            }

但是由于应用程序错误关闭而仍然无法正常工作。

0 个答案:

没有答案