使用库中的函数同步wpf进度条的正确方法

时间:2016-01-27 09:39:07

标签: c# wpf progress-bar

我正在使用库中的函数来处理非常大的单词文件,我无法更改此功能。 在处理时,我想显示一个进度条,因为无论哪种方式,应用程序看起来都冻结了,而且用户并不知道它实际上正在工作。 现在我正在使用这样的工人:

private void btnClick(object sender, RoutedEventArgs e)
{ 
    BackgroundWorker worker = new BackgroundWorker();
    worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    worker.WorkerReportsProgress = true;
    worker.DoWork += worker_DoConvertOne;
    worker.ProgressChanged += worker_ProgressChanged;
    worker.RunWorkerAsync();
}

private void worker_DoConvertOne(object sender, DoWorkEventArgs e)
{
    var worker = sender as BackgroundWorker;
        //The progress bar is filled on 20%
        worker.ReportProgress(0);
        worker.ReportProgress(10);
        worker.ReportProgress(20);

        //Processing
        myLongLastingFunction(bigWordFile);

        //The progress bas is full
        worker.ReportProgress(100, "Done Processing.");
}

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    MessageBox.Show("Converting finished!");
    TestProgressBar.Value = 0;
    ProgressTextBlock.Text = "";
}

private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    TestProgressBar.Value = e.ProgressPercentage;
    ProgressTextBlock.Text = (string)e.UserState;
}

它正在做这项工作,但它是一种解决方法,我想知道是否有正确的方法来解决我的问题。提前致谢。 :)

4 个答案:

答案 0 :(得分:3)

我从你的问题中得知,改变myLongLastingFunction是不可能定期向你提供有关进展的更新,而且这项功能目前在功能中不存在。

对于无法确定任务持续时间的这些情况,具有依赖项属性IsIndeterminate="True"的进度条是将此信息提供给用户的可接受方式。这会使进度条连续滚动。

XAML

   <ProgressBar Margin="10" IsIndeterminate="True" />

我个人更喜欢Windows Phone上看到的动画移动点。已经实施了一个示例here

如果这不是您所需要的,则下一个最佳方法是估计总时间,并使用DispatchTimer细分此时间以提供周期性事件以增加进度条。这显然有两个问题,要么在达到100%之前完成(不是坏事)或达到100%并且因为实际时间明显长于估计而卡在那里。第二个不良影响将使应用程序再次处于非活动状态。

答案 1 :(得分:2)

如果您使用4.5,那么您可以使用IProgress。请参考这个例子 [https://code.msdn.microsoft.com/Progress-of-a-Task-in-C-cdb179ee][1]

答案 2 :(得分:2)

在阅读.txt(Word)文件时,可以通过ProgressBarBackgroundWorker显示当前进度。您应该只计算1 percent的{​​{1}}的比例。让我们看看工作示例:

代码背后:

ProgressBar

<强> XAML:

public partial class MainWindow : Window
{
    BackgroundWorker bw;
    long l_file;
    public MainWindow()
    {
        InitializeComponent();
    }

    string fileName = "";
    private void InitializeBackgroundWorker()
    {   
        bw = new BackgroundWorker();
        bw.DoWork += Bw_DoWork;
        bw.ProgressChanged += Bw_ProgressChanged;            
        bw.WorkerReportsProgress = true;
    }



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

    private void Bw_DoWork(object sender, DoWorkEventArgs e)
    {
        ReadFile(fileName);
    }

    private void btnOpenFLD_Click(object sender, RoutedEventArgs e)
    {
        progressBar.Minimum = 0;
        progressBar.Maximum = 100;

        OpenFileDialog ofd = new OpenFileDialog();            
        if (ofd.ShowDialog() == true)
        {                
            FileInfo fileInfo = new FileInfo(ofd.FileName);
            l_file = fileInfo.Length;
            fileName = ofd.FileName;
            InitializeBackgroundWorker();
            bw.RunWorkerAsync();
        }            
    }        

    private void ReadFile(string fileName)
    {
        string line;
        long onePercent = l_file / 100;
        long lineLength = 0;
        long flagLength = 0;
        using (StreamReader sr = new StreamReader(fileName, System.Text.Encoding.ASCII))
        {
            while (sr.EndOfStream == false)
            {
                line = sr.ReadLine();
                lineLength = line.Length;
                flagLength += lineLength+2;
                //Thread.Sleep(1);//uncomment it if you want to simulate a 
                //very heavy weight file
                if (flagLength >= onePercent)
                {
                    CountProgressBar += 1;
                    bw.ReportProgress(CountProgressBar);
                    flagLength %= onePercent;
                }
            }
        }
    }

    int countProgressBar = 0;
    private int CountProgressBar
    {
        get { return countProgressBar; }
        set
        {
            if (countProgressBar < 100)
                countProgressBar = value;
            else
                countProgressBar = 0;
        }
    }
}    

如果您在阅读文件后执行其他工作并且想要显示进度,那么只需在完成所有工作后移动此代码。

<Window x:Class="BackgroundWorkerProgressBarReadFile.MainWindow"
        ...The code omitted for the brevity...
        xmlns:local="clr-namespace:BackgroundWorkerProgressBarReadFile"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.2*"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>            
        </Grid.ColumnDefinitions>
        <ProgressBar Margin="5" Name="progressBar"/>
        <Button Grid.Row="1" Content="Open File Dialog" Name="btnOpenFLD"  
        Click="btnOpenFLD_Click"/>


    </Grid>
</Window>

答案 3 :(得分:1)

如果您的myLongLastingFunction没有报告任何进展,则无法确定其工作量在任何时候都已完成。

然而,Satyaki Chatterjee已经建议你可以使用无限进度条。