Link to home
Create AccountLog in
Avatar of davecove
davecoveFlag for United States of America

asked on

Trying to thread

Here is a little Form project I am using as a training exercise for myself (first time using a bool terminate signal instead of Thread.Abort()).  I would expect it to work, but it doesn't. The problem is this:

When the Worker method is kicked off by Thread.Start, the value of KeepWorking is true and InvokeRequired is true.  When the worker method is entered again because of the BeginInvoke, KeepWorking is false. The main thread is keeping the value of KeepWorking set to true for 10 seconds, so I don't see why it is false during the BeginInvoke pass.

Help?

Dave
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace Scratch
{
    public partial class Form1 : Form
    {
        public static bool KeepWorking = true;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            KickOff();
        }

        private void KickOff()
        {
            KeepWorking = true;
            Thread t = new Thread(new ParameterizedThreadStart(Worker));
            t.Start("something");
            Thread.Sleep(10000);
            KeepWorking = false;
        }

        private void Worker(object obj)
        {
            string s = (string)obj;

            if (textBox1.InvokeRequired)
            {
                textBox1.BeginInvoke(new Action<object>(Worker), obj);
            }
            else
            {
                int i = 0;
                while (KeepWorking)
                    textBox1.Text = i++.ToString();
            }
        }        
    }
}

Open in new window

Avatar of wdfdo1986
wdfdo1986
Flag of Sri Lanka image

although u are talking about the threads u are trying to do it sequentially.
For further help I need to know the content of the method "something".
Avatar of davecove

ASKER

No... it is threading...

t.Start() kicks off Worker on its own thread and passes it the string "something" as a parameter.  "something" is a parameter passed to Worker... not a method.

Worker spins thru a bunch of textbox.text changes while the main thread sleeps for 1000ms. The BeginInvoke is so that Worker can access something that belong's to main's thread.

After 1000ms the main thread continues by changing the KeepWorking boolean. This causes the Worker to exit the while() and terminate.

Dave
ok sorry I misread the code
I'll test this code before tell something
try this code

            if (textBox1.Dispatcher.CheckAccess())
            {
                textBox1.Dispatcher.BeginInvoke(new Action<object>(Worker), obj);
            }
            else
            {
                int i = 0;
                while (KeepWorking)
                    textBox1.Text = i++.ToString();
            }

http://stackoverflow.com/questions/2017364/accessing-2-ui-items-from-a-3rd-thread-in-wpf
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
wdfdo1986 : I'm not using WPF... so no Dispatcher ??

Idle Mind : Ok, I see that now... so how is this solution? The worker thread does not try to update anything on the UI... when it has something to say, it calls an UpdateText function that does the BeginInvoke to get back on the UI thread, leaving the Worker to continue.

The main thread does not sleep, is spawns a Timer thread that does the sleeping for it and sets the flag at the end of the nap.

This seems to work, other than the TextBox never got updated until the very end. No interim updates.

Dave
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Scratch
{
    public partial class Form1 : Form
    {
        public static bool KeepWorking = true;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            KickOff();
        }

        private void KickOff()
        {
            KeepWorking = true;
            Thread t = new Thread(new ParameterizedThreadStart(Worker));
            t.Start("something");
            Thread w = new Thread(new ParameterizedThreadStart(Timer));
            w.Start(10000);            
        }

        private void Worker(object obj)
        {
            string s = (string)obj;
            int i = 0;
            while (KeepWorking)
            {
                // simulate some work
                Thread.Sleep(1000);
                // Now update the UI
                UpdateText(i++.ToString());
            }            
        }

        private void UpdateText(string _text)
        {
            if (textBox1.InvokeRequired)
            {
                textBox1.BeginInvoke(new Action<object>(Worker), _text);
            }
            else
            {
                textBox1.Text = _text;
            }
        }

        private void Timer(object obj)
        {
            int wait = (int)obj;

            Thread.Sleep(wait);
            KeepWorking = false;
        }        
    }
}

Open in new window

Try changing:

    textBox1.BeginInvoke(new Action<object>(Worker), _text);

To:

    textBox1.BeginInvoke(new Action<object>(UpdateText), _text);

Have you considered using the BackgroundWorker() control instead?
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx