C#, WPF, Updating the gui without backgroundworkers

后端 未结 3 1518
有刺的猬
有刺的猬 2021-02-11 06:27

I have a program that takes 10-20 seconds to start. I need to show a window with a progress bar when the program starts up. I know BackgroundWorker\'s are the correct way to do

相关标签:
3条回答
  • 2021-02-11 07:07

    It really is very easy to use backgroundworker.

    public partial class Window1 : Window
    {
        BackgroundWorker worker = new BackgroundWorker();
    
        public Window1()
        {
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.ReportsProgress = true;
            worker.ProgressChanged += new ProgressChangedEventHandler(update_progress);
        }
    
    
        void worker_DoWork(object sender, DoWorkEventArgs e){
            DoSomeLongTask();
            //call worker.ReportProgress to update bar
        }
    
        void update_progress(object sender, ProgressChangedEventArgs e)
        {
            myscrollbar.Value = e.Value;
        }
    }
    

    The keything to keep in mind is to never touch gui stuff from DoWork method. That has to through ProgressChanged/ReportProgress

    0 讨论(0)
  • 2021-02-11 07:12

    If you don't want the background worker you need to adjust your code, to do the long task in the new thread.

    using System;
    using System.Threading;
    using System.Windows;
    
    namespace WpfApplication1
    {
      public partial class Window1 : Window
      {
          public Window1()
          {
              InitializeComponent();
    
              Thread t = new Thread(DoSomeLongTask);
              t.Start();
    
              // switch this with the DoSomeLongTask, so the long task is
              // on the new thread and the UI thread is free.
              ShowLoadingWindow();
        }
      }
    }
    

    If you want to then update a progress bar from your "DoSomeLongTask" method then you'll need to ensure that you call invoke. For example:

    delegate void ProgressDelegate(int Progress);  
    private void UpdateProgress( int  Progress)  
    {  
       if (!progressBar1.Dispatcher.CheckAccess())  
       {  
         progressBar1.Value = Progress;  
       }  
       else  
       {  
         ProgressDelegate progressD = new ProgressDelegate(UpdateProgress);  
         progressBar1.Dispatcher.Invoke(progressD, new object[] { Progress });  
       }  
    }  
    
    0 讨论(0)
  • 2021-02-11 07:14

    You're still doing the long task in the main thread. You need to show the loading window in the main thread and do the long task in the background.

    Using a BackgroundWorker is really the simplest solution for this:

    BackgroundWorker bw;
    LoadingWindow lw;
    
    public Window1() {
        bw = new BackgroundWorker();
        lw = new LoadingWindow();
    
        bw.DoWork += (sender, args) => {
            // do your lengthy stuff here -- this will happen in a separate thread
            ...
        }
    
        bw.RunWorkerCompleted += (sender, args) => {
            if (args.Error != null)  // if an exception occurred during DoWork,
                MessageBox.Show(args.Error.ToString());  // do your error handling here
    
            // close your loading window here
            ...
        }
    
        // open and show your loading window here
        ...
    
        bw.RunWorkerAsync(); // starts the background worker
    }
    
    0 讨论(0)
提交回复
热议问题