views:

131

answers:

2

Here is my scenario: I have a Main ParentWindow . Before opening the parent i would like to open a progressWindow and fetch the data from DB displaying this window. After the data fetch is complete i would like to close the progressWindow by using a delegate and i am running into threading issues. Just wondering if you have any suggestions:


Here is the code for ParentWindow:


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.Shapes;

namespace RounderProgressBar {

/// <summary>
/// Interaction logic for Window2.xaml
/// </summary>

public partial class ParentWindow : Window
{

    public ParentWindow()
    {
        InitializeComponent();

        progress = new ProgressWindow();
        progress.publisher = this.Subscriber;
        progress.ShowDialog();
    }
    ProgressWindow progress;// = new Window1();
    protected EventHandlerWithParms _subscriber;
    protected EventHandlerWithParms Subscriber
    {
        get
        {
            if (_subscriber == null)
            {
                _subscriber = new EventHandlerWithParms(Execute);
            }
            return _subscriber;
        }
    }
    private void Execute(object sender, EventArgs e)
     {
        (sender as Window).Close();//.Dispatcher.Invoke(Subscriber,null);//.InvokeShutdown();//.Close();

        //progress.Close();
        //this.Close();
        //Window w = new Window();
        //w.ShowDialog();
    }
}

}


Here is the child or progressWindow:


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 System.ComponentModel;

using System.Collections;

namespace RounderProgressBar {

/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>

public partial class ProgressWindow : Window

{

    public ProgressWindow()

    {

        InitializeComponent();

        StartWorker(null, null);
    }

    private BackgroundWorker _worker;

    private void StartWorker(object sender, RoutedEventArgs e)
    {
        _worker = new BackgroundWorker();
        _worker.WorkerReportsProgress = true;
        _worker.WorkerSupportsCancellation = true;

        _worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            BackgroundWorker worker = s as BackgroundWorker;
            //for (int i = 0; i < 10; i++)
            //{
            if (worker.CancellationPending)
            {
                args.Cancel = true;
                return;
            }

            //System.Threading.Thread.Sleep(1000);
            runInBack();
            //int max = int.Parse((_progressBar.Maximum - 1).ToString());

            //If we comment this it will go into infinite loop as completed will never get triggered
            //worker.ReportProgress(/*max*/9);//worker.ReportProgress(9);//worker.ReportProgress(i + 1);
            worker.ReportProgress(9);
            //}
        };

        _worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args)
        {
            //_progressBar.Value = args.ProgressPercentage;
        };

        _worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
        {
            //_btnStart.IsEnabled = true;
            //_btnCancel.IsEnabled = false;
            //_progressBar.Value = 0;
        };

        _worker.RunWorkerAsync();
        //_btnStart.IsEnabled = false;
        //_btnCancel.IsEnabled = true;
    }
    private void runInBack()
    {
        System.Threading.Thread.Sleep(3000);
        //IsBusExecuted = true;
        if (this.publisher != null)
            publisher(this, null);
    }
    public EventHandlerWithParms publisher;
    private void CancelWorker(object sender, RoutedEventArgs e)
    {
        _worker.CancelAsync();
    }

    private bool IsBusExecuted = false;
    void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (IsBusExecuted)
        {
            t.Stop();
            MessageBox.Show("1");
            this.rpb.Stop();
        }

    }

    private void Execute(object sender, EventArgs e)
    {
        this.Close();
    }

    private System.Timers.Timer t = new System.Timers.Timer(1000);
}
public delegate void EventHandlerWithParms(object sender, EventArgsWithParms e);
public class EventArgsWithParms : EventArgs
{
    public EventArgsWithParms()
    {
    }
    public Hashtable ParmTable = new Hashtable();
}

}

A: 

First of all, calling ShowDialog in InitiallizeComponents method will block UI and not very good solution; No events will be forwarded to GUI thread and that's why it will never close. Close() method of child form must call its own close when tasks are finished;

Yurec
A: 

Don't close the ProgressWindow in the Execute method, because that's running on the background thread and shouldn't manipulate objects on the UI thread. Close it in the BackgroundWorker's RunWorkerCompleted delegate, which executes on the UI thread once the task is finished.

Robert Rossney