如何异步更新显示信息的标签

时间:2017-04-19 07:25:50

标签: c# wpf xaml label

我正在使用wpf,我需要用类更新视图的元素。 所以,我有三个文件:

  • MainWindow.xaml - >我要更新的元素是。
  • MainWindow.xaml.cs - >我调用其他类的函数(utils.cs)。
  • Utils.cs - >我们可以在哪里找到函数freeSpace()(这个函数计算磁盘上的可用空间),在这个函数中我想更改MainWindow.xaml中的标签。

我需要更改的元素是标签。

为什么mainwindow自己的代码无法从函数中获取新名称并自行进行更改? 我希望在主窗口代码之外完成计算,以便获得清晰的代码。

我遇到的问题是在Utils.cs中我有两个函数,copy()和freeSpace()。复制功能复制文件并调用freeSpace。在自由空间中,我有一个循环,每隔10秒检查一次freeSpace,直到副本完成。因此,每10秒我需要更改代表可用空间的标签。

MainWindow.xaml

<Label x:Name="freeSpaceLabel"></Label>

MainWindow.xaml.cs

   private void btnStart_Click(object sender, RoutedEventArgs e)
    {
        Utils u = new Utils();
        u.copy();
    }

Utils.cs

  private void freeSpace(){
            while (isFinish())
            {
                 // Update the label    
                  [...] 
                  drive.TotalFreeSpace; //return an int, I just want to set this int to the label of my view.
                  [...]
                  Thread.Sleep(10000); 
            }
    }

private void isFinish(){
    // Return true if the copy is finish
    // Return false if the copy is not finish
}

private void copy(){
    //Copy a file 
    freeSpace();
}

我不认为传递视图是一个很好的解决方案。

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

添加此代码以使您的任务异步:

private async void DoyourWorkHere()
{   
  await Task t = Task.Run( () => 
  {
      Utils u = new Utils();
       u.copy();
  } );    
}

点击按钮调用此方法。

  

更新标签:

您可以创建事件和委托以将信息发送回MainWindow,或者您可以将MainWindow作为参数发送到util类,并从Util类调用公共属性来更新您的Label

答案 1 :(得分:0)

您可能根本不需要Util.cs。

您需要的是BackgroundWorker和ProgressChanged。试试这个:

<强> Stack_43489182.xaml:

<Window x:Class="Wpf.Test01.Stack_43489182"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Wpf.Test01"
        mc:Ignorable="d"
        Title="Stack_43489182" Height="300" Width="300">
    <DockPanel>
        <Button x:Name="btnStartAsync" Content="Start Async" DockPanel.Dock="Top" Click="Button_Click" />
        <ProgressBar x:Name="progressBar" Minimum="0" Maximum="100" />
    </DockPanel>
</Window>

<强> Stack_43489182.xaml.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Wpf.Test01
{
    /// <summary>
    /// Interaction logic for Stack_43489182.xaml
    /// </summary>
    public partial class Stack_43489182 : Window
    {
        private BackgroundWorker worker;
        public Stack_43489182()
        {
            InitializeComponent();

            this.worker = new BackgroundWorker();
            this.worker.DoWork += Worker_DoWork;
            this.worker.ProgressChanged += Worker_ProgressChanged;
            this.worker.WorkerReportsProgress = true;
        }

        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar.Value = e.ProgressPercentage;
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            /** you need to put code from Util.cs here **/

            int i = 1;
            while(i <= 10)
            {
                this.worker.ReportProgress((int)((i / (double)10) * 100));

                Thread.Sleep(1000);
                i++;
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            progressBar.Value = 0;
            this.worker.RunWorkerAsync();
        }
    }
}

您甚至可以实施取消来停止您的操作。

请参阅此示例以了解如何使用BackgroundWorker: https://www.codeproject.com/Articles/99143/BackgroundWorker-Class-Sample-for-Beginners

如果您需要重复使用Util类

<强> Stack_43489182.xaml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace Wpf.Test01
{
    /// <summary>
    /// Interaction logic for Stack_43489182.xaml
    /// </summary>
    public partial class Stack_43489182 : Window
    {
        private BackgroundWorker worker;
        private Utils util;

        public Stack_43489182()
        {
            InitializeComponent();

            this.worker = new BackgroundWorker();
            this.worker.DoWork += Worker_DoWork;
            //this.worker.ProgressChanged += Worker_ProgressChanged;
            this.worker.WorkerReportsProgress = true;

            this.util = new Utils();
            util.FreeSpace_ProgressChanged += Worker_ProgressChanged;
        }

        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
                                                       new Action(() => this.progressBar.Value = e.ProgressPercentage));
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            var utils = e.Argument as Utils;

            if(utils != null)
            {
                utils.copy();
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            progressBar.Value = 0;
            this.worker.RunWorkerAsync(util);
        }

        public class Utils
        {
            public event ProgressChangedEventHandler FreeSpace_ProgressChanged;

            private void freeSpace()
            {
                int i = 1;
                while (!isFinished(i))
                {

                    if(FreeSpace_ProgressChanged != null)
                    {
                        FreeSpace_ProgressChanged(i, new ProgressChangedEventArgs((int)((i / 10.0) * 100), null));
                    }

                    Thread.Sleep(1000);

                    i++;
                }
            }

            private bool isFinished(int i)
            {
                // Return true if the copy is finish
                // Return false if the copy is not finish
                return i == 10 ? true : false;
            }

            public void copy()
            {
                //Copy a file 
                freeSpace();
            }
        }
    }
}