后台工作人员无法流畅地渲染窗口

发布于 2024-12-16 22:31:06 字数 3774 浏览 0 评论 0原文

我刚刚进入 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);        
            }
        }
    }

谢谢,

丹尼斯

I just got into WPF and am currently trying my luck with the Background worker, so I figured I'd just open any file using the FileOpenDialog, loop through all the bytes inside the file and report the total progress via worker.ReportProgress in percentage ... alas, this only works for like ~20 times and then it gets really stuck and suddenly stops at 100%.

Here's my code:

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)
    {
    }
}

}

Labels 1 and 2 are there for showing the current byte and the current progress in %.

Feel free to also criticize every other aspect of my code, I just got started with WPF today.

Edited 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);        
            }
        }
    }

Thanks,

Dennis

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

少女七分熟 2024-12-23 22:31:06

因此,假设您确实想对每个字节进行跨线程调用(我不建议这样做),那么代码将类似于:

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 的线程上操作它。

So assuming you really want to make a cross thread call for each byte (which I wouldn't recommend), the code would look something like:

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); 
        } 
    } 
} 

The idea being that you can only manipulate a DispatcherObject on the thread on which it was created.

打小就很酷 2024-12-23 22:31:06

首先想到的是你没有处理 openfiledialog 的返回结果,所以你运行它的次数越多,你扔掉的资源就越多......
我会将文件名扔给工作人员,然后让它管理资源,但

using(Stream s = ofd.OpenFileDalog())
{
   get length and such
}
// run up woker pass filename.

在您的调用代码中将解决问题,因为我假设您正在使用长度来整理进度条。

First thought is you aren't disposing the return from the openfiledialog so the more times you run it the more resources you throw away...
I would have thrown the filename at the worker and then let it manage the resource, but

using(Stream s = ofd.OpenFileDalog())
{
   get length and such
}
// run up woker pass filename.

in your calling code will solve the problem, as I'm assuming you are using length to sort out your progress bar.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文