后台工作者不工作WPF [英] Background worker does not Work WPF

查看:71
本文介绍了后台工作者不工作WPF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的WPF程序中,它花费了大量的处理时间并冻结了很长时间.

In my WPF program it took huge processing time and freezing for long time.

所以我决定使用后台工作程序并在后台对其进行处理.

so I decided to use background worker and process it in background.

,但是它不起作用.通过调试,程序在Render3D()处停止.它不会引发异常.就像您放入return一样.

but it does not work. through debug, the program stop at Render3D(). It does not throw exception. Its like when you put return.

换句话说,到达Render3D()后它什么也不做,只会返回.

In other word it does nothing after reaching Render3D() and will just return.

(我不会说它将返回,因为我不确定,但行为与return相同)

(I don't say it will return Because im not sure but the behavior is same as return)

    private readonly BackgroundWorker backgroundWorker = new BackgroundWorker();
    private AssetDeclaration _assetDeclaration = new AssetDeclaration();

    public MainWindow()
    {
        backgroundWorker.DoWork += backgroundWorker1_DoWork;
        backgroundWorker.ProgressChanged += backgroundWorker1_ProgressChanged;
        backgroundWorker.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
        InitializeComponent();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 1; i <= 1000; i++)
        {
            if (!((BackgroundWorker)sender).CancellationPending)
            {
                Render3D(); // will return at this point. (why?) or waiting for something to start?
                ((BackgroundWorker)sender).ReportProgress(i);
            }
            else
            {
                e.Cancel = true;
                break;
            }
        }
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        MessageBox.Show("Done!");//will show message box instant.
    }

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

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        //...Some work here before starting Hard job!
        //...From now i want to start heavy process in background.
        //...with report to progress bar at same time.
        backgroundWorker.RunWorkerAsync(100);
    }

Render3D()无需后台处理即可正常工作,但会冻结一段时间.

Render3D() works fine without Background processing but will freeze for some time.

Render3D()在MainWindowPartial类中.因为有很多方法,所以我决定将它们分开.

Render3D() is in Partial class of MainWindow .because there are lots of methods so i decided to separate them.

我又如何在backgroundWorker1_DoWork之外使用ReportProgress.例如在Render3D()中.

Also how can I use ReportProgress outside backgroundWorker1_DoWork . for example in Render3D().

最后一件事:我想知道如何向用户展示完成了多少过程.

Last thing : i want to know how to show the user how much of process is done.

已解决!:

问题是因为我在Render3D()

我将其与Render3D分离,问题得以解决.感谢Henk Holterman的正确回答.

I separated it from Render3D and problem got fixed. thanks to Henk Holterman for the right answer.

似乎有些任务无法在另一个线程中完成.通过错误报告,我发现无效的任务正在设置Viewport3D属性.

It seems some tasks cant be done in another Thread. with the Error report i find out that the invalid task is setting Viewport3D properties.

此任务必须在主线程中完成.

this tasks must be done in Main thread.

下面的无效代码使后台工作程序停止运行.

below is invalid Code that made background worker stop functioning.

DefineCamera();
Viewport.Children.Add(model); // Must be run in Main thread.

还有这部分.

    private void DefineCamera()
    {
        PerspectiveCamera camera = new PerspectiveCamera
        {
            FieldOfView = 60
        };

        PositionCamera(camera);
        Viewport.Camera = camera; // Must be run in Main thread.
    }

推荐答案

首先,您很难找到错误.

First of all, you had trouble finding the error.

...程序在Render3D()处停止.它不会引发异常.就像您放回程证一样.

... the program stop at Render3D(). It does not throw exception. Its like when you put return.

实际发生的事情是您的方法引发了一个异常,并由Backgroundworker捕获了该异常.它已转移到Completed事件,但是您必须在该事件上执行操作.

What actually happened was that an exception was thrown by your method and was captured by the Backgroundworker. It is transferred to the Completed event but you do have to act on it there.

private void worker_Completed(object sender, RunWorkerCompletedEventArgs e) 
{
  // check error, check cancel, then use result
  if (e.Error != null)
  {
     // handle the error
  }
  else if (e.Cancelled)
  {
     // handle cancellation
  }
  else      
  {         
      // use the result(s) on the UI thread
  }    
  // general cleanup
}

不查看e.Errore.Result都与在程序中具有空的catch{}块相同.

Failing to look at either e.Error or e.Result is the same as having an empty catch{} block in your program.

然后通过错误处理就可以了

And with error handling in place we then have

哦,是的,它显示错误. System.InvalidOperationException调用线程无法访问此对象,因为其他线程拥有它

oh yes it shown Error. System.InvalidOperationException the calling thread cannot access this object because a different thread owns it

这表明您的Render3D()仍在某处与GUI交互.

This indicates that your Render3D() still interacts with the GUI somewhere.

基本建议是将所有计算(以及I/O,数据库)工作与UI工作分开.您可以在一个线程中运行CPU绑定和I/O绑定的cod,但是GUI是单线程的,您只能从主线程与之交互.

The basic advice is to separate all the calculation (and I/O, database) work from the UI work. You can run the CPU bound and I/O bound cod in a thread but the GUI is single threaded, you can only interact with it from the main Thread.

这篇关于后台工作者不工作WPF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆