我刚进入WPF并且我正在尝试使用后台工作程序,所以我想我只需使用FileOpenDialog
打开任何文件,循环遍历文件中的所有字节并报告总进度通过worker.ReportProgress
百分比...唉,这只能工作约20次然后它真的卡住了,突然停在100%。
这是我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using System.IO;
using System.Threading;
using System.ComponentModel;
namespace BitStream
{
public partial class MainWindow : Window
{
private int bytes = 0;
private long length = 0;
public MainWindow()
{
InitializeComponent();
}
private void selectFile_Click(object sender, RoutedEventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
OpenFileDialog ofd = new OpenFileDialog();
if ((bool)ofd.ShowDialog())
{
FileInfo fi = new FileInfo(ofd.FileName);
this.length = fi.Length;
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.ProgressChanged += bw_ProgressChanged;
bw.WorkerReportsProgress = true;
Stream str = ofd.OpenFile();
bw.RunWorkerAsync(str);
}
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
Stream str = (Stream)e.Argument;
int singleByte = 0;
this.Dispatcher.Invoke(
new Action(() =>
{
int currentProgress = 0;
while ((singleByte = str.ReadByte()) != -1)
{
label1.Content = singleByte;
bytes++;
currentProgress = Convert.ToInt32(((double)bytes) / length * 100);
if (currentProgress > progress)
{
progress = currentProgress;
((BackgroundWorker)sender).ReportProgress(progress);
Thread.Sleep(100);
}
}
}
), System.Windows.Threading.DispatcherPriority.Render);
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label2.Content = e.ProgressPercentage + "% completed";
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
}
}
标签1和2用于显示当前字节和当前进度%。
随意批评我代码的其他方面,我今天刚刚开始使用WPF。
编辑的DoWork-Method:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
Stream str = (Stream)e.Argument;
int singleByte = 0;
int currentProgress = 0;
while ((singleByte = str.ReadByte()) != -1)
{
this.Dispatcher.Invoke(
new Action(() =>
{
label1.Content = singleByte;
}), System.Windows.Threading.DispatcherPriority.Render);
bytes++;
currentProgress = Convert.ToInt32(((double)bytes) / length * 100);
if (currentProgress > progress)
{
progress = currentProgress;
this.Dispatcher.Invoke(
new Action(() =>
{
((BackgroundWorker)sender).ReportProgress(progress);
}), System.Windows.Threading.DispatcherPriority.Render);
Thread.Sleep(500);
}
}
}
谢谢,
丹尼斯
答案 0 :(得分:1)
所以假设你真的想为每个字节做一个跨线程调用(我不推荐),代码看起来像:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
Stream str = (Stream)e.Argument;
int singleByte = 0;
int currentProgress = 0;
while ((singleByte = str.ReadByte()) != -1)
{
bytes++;
this.Dispatcher.Invoke(
new Action(() =>
{
label1.Content = singleByte;
}
), System.Windows.Threading.DispatcherPriority.Render);
currentProgress = Convert.ToInt32(((double)bytes) / length * 100);
if (currentProgress > progress)
{
progress = currentProgress;
((BackgroundWorker)sender).ReportProgress(progress);
Thread.Sleep(100);
}
}
}
这个想法是你只能在创建它的线程上操作DispatcherObject。
答案 1 :(得分:1)
首先想到的是你没有处理openfiledialog的返回,所以你运行它的次数越多,你丢弃的资源就越多...... 我会将文件名抛出给worker,然后让它管理资源,但是
using(Stream s = ofd.OpenFileDalog())
{
get length and such
}
// run up woker pass filename.
你的调用代码中的将解决问题,因为我假设你使用长度来整理你的进度条。