1

this is the simplified plan for a solution: for some reasons i need to run a windows form through a backgroundworker that is runnig by another backgroundworker, when the new windows form loads, the older backgroundworker must pause. i write the code like this :

creating a class with name : temp

public class temp
{
    static public BackgroundWorker backgroundWorker1 = new BackgroundWorker() { WorkerSupportsCancellation = true };
    static public EventWaitHandle ew = new EventWaitHandle(false, EventResetMode.ManualReset);
    static public BackgroundWorker back = new BackgroundWorker() { WorkerSupportsCancellation = true };   
}

the codes for form1 are :

namespace WindowsFormsApplication1
{

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

       Control.CheckForIllegalCrossThreadCalls = false;
       temp.backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
        temp.back.DoWork += new DoWorkEventHandler(back_DoWork);          
    }

    void back_DoWork(object sender, DoWorkEventArgs e)
    {
        Form2 f = new Form2();
        f.Show();
    }
    private void button1_Click(object sender, EventArgs e)
    {

        temp.backgroundWorker1.RunWorkerAsync();

    }

   private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {

            temp.back.RunWorkerAsync();

            if (temp.backgroundWorker1.CancellationPending)
               temp.ew.WaitOne();
    }

   }
}

and the codes of form2 goes here :

namespace WindowsFormsApplication1
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }



    private void Form2_Load(object sender, EventArgs e)
    {

     temp.backgroundWorker1.CancelAsync();
     temp.ew.Reset();
    }

   }
}

by clicking the button1 from form1 the temp.backgroundworker1 runs and then in the DoWork of temp.backgroundworker1, the temp.back runs and then FORM2 LOADS BUT THE FORM2 HANGS AND BECOMES USELESS AND YOU CANNOT USE THAT ANY MORE. where did i wrong ? the whole plan that i'm going to execute is : we have a For loop that processes every row of a DataGridView. each time in a certain point, another windowsform opens and it stops the loop until the user inserts the information and then click on OK button, the windowsform closes and the loop keep on working. i dont know what to do.......

even if i dont cancel working of the temp.backgroundworker in form2load like the code below, the Form2 is useless

private void Form2_Load(object sender, EventArgs e)
    {   


    }
Hnz
  • 57
  • 6

1 Answers1

0

Do not use any UI operation in the work thread (DoWork method). Maybe that's why you set the CheckForIllegalCrossThreadCalls property, but your app will not work properly just suppresses the error when the debugger is attached.

See my answer here for the correct usage of the BackgroundWorker (that is about canceling but you can see the operations in UI and worker thread).

In this particular case what you can use a similar volatile bool to sign the UI thread that the form can be shown. Or, if you want to send different messages between the threads, use a ConcurrentQueue<T> to write and read messages:

public partial class Form1 : Form
{
    private enum Message
    {
        ShowForm2,
        SuspendWork,
        ResumeWork,
        FinishWorker1
        // ... and whatever you want
    }

    private Timer timer;
    private ConcurrentQueue<Message> messagesToUI = new ConcurrentQueue<Message>();
    private ConcurrentQueue<Message> messagesToWorker = new ConcurrentQueue<Message>();

    public Form1()
    {
        InitializeComponent();
        timer = new Timer(this);
        timer.Interval = 10;
        timer.Tick += PollUIMessages;
        timer.Enabled = true;
    }

    void PollUIMessages(object sender, EventArgs e)
    {
        // do we have a new message?
        Message message;
        if (messagesToUI.TryDequeue(out message))
        {
            switch (message)
            {
                case Message.ShowForm2:
                    Form2 f = new Form2();
                    f.Show();
                    // todo: in Form2.Close add a Resume message to the messagesToWorker
                    break;

                // ... process other messages
            }
        }
    }

    void back_DoWork(object sender, DoWorkEventArgs e)
    {
        // Here you are in the worker thread. You can send a message to the
        // UI thread like this:
        messagesToUI.Enqueue(Message.ShowForm2);

        bool isWorking = true;

        // and here you can poll the messages to the worker thread
        while (true)
        {
            Message message;
            if (!messagesToWorker.TryDequeue(out message))
            {
                // no message: idle or work
                if (isWorking)
                    DoSomeWork(); // do whatever you want
                else
                    Thread.CurrentThread.Sleep(10);
                continue;
            }

            switch (message)
            {
                case Message.FinishWorker1:
                    // finishing the worker: jumping out
                    return;
                case Message.SuspendWork:
                    isWorking = false;
                    break;
                case Message.ResumeWork:
                    isWorking = true;
                    break;
            }
        }
    }
Community
  • 1
  • 1
György Kőszeg
  • 17,093
  • 6
  • 37
  • 65
  • i did not get what you do as i'm new in c#, but i do another code that it worked.... i defined a new thread that shows a windows form : void UI() { using (Form2 f = new Form2()) f.ShowDialog(); } Thread ui = new Thread(UI); and ran it from the DoWork of temp.backgroundworker, now from Form2 i can control the process of the temp.backgroundworker...... it looks correct, but i don't know is that common or right to use a thread in this way... – Hnz Dec 03 '15 at 22:59
  • If you start a thread explicitly, it is needless to use a `BackgroundWorker`. On the other hand, you are still not allowed to access a control from a foreign thread. – György Kőszeg Dec 04 '15 at 08:17