2017-04-19 65 views
2

我正在使用wpf,我需要使用類更新視圖的元素。 所以,我有三個文件:如何異步更新顯示信息的標籤

  • MainWindow.xaml - >我在哪裏要更新的元素。
  • MainWindow.xaml.cs - >我在哪裏調用其他類的函數(utils.cs)。
  • Utils.cs - >在這裏我們可以找到函數freeSpace()(這個函數計算磁盤上的空閒空間),在這個函數中我想改變MainWindow.xaml中的一個標籤。

我需要改變的元素是一個標籤。

爲什麼mainwindow自己的代碼不能從函數中獲得一個新名字並自己做出更改? 我想要在主窗口代碼之外完成計算,以獲得清晰的代碼。

我在這種情況下的問題是,在Utils.cs我有兩個函數,copy()和freeSpace()。複製功能複製文件並調用freeSpace。在自由空間中,我有一個循環,每10秒檢查一次空閒空間,直到複製完成。所以每隔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(); 
} 

我不認爲傳遞的看法是一個很好的解決方案。

感謝您的幫助!

回答

0

添加以下代碼,使您的工作Asyncrounous:

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

從電話按鈕單擊此方法。

用於更新標籤:

您可以創建活動,並委託發送信息回你的主窗口,也可以從的Util類發送主窗口作爲參數的Util類,並調用一個公共屬性來更新您標籤

+0

這不是異步,它在一個單獨的線程池線程上執行,事實上在這個'Task.Run'中也是首選。也等待任務塊的主線程,這打敗了目的 –

+0

哦,我沒有注意到等待方法編輯 – tabby

+0

現在它不會停止任務完成:)和按鈕啓動將完成執行,您需要Async -Await,因爲這是隻有機制才能完成 –

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(); 
      } 
     } 
    } 
} 
+0

而不是co尋找一些代碼,你應該修改它來解決代碼要求OP建議 –

+1

我給出了一個解決方案的想法。我認爲作者應該做出一些努力 –

+0

問題是想法也過時了,因爲Async Await能夠更高效地完成相同的工作 –