Passing parameters in threads. C# or Visual C++??

Permabanned
Joined
15 Nov 2006
Posts
164
Location
Visit Athens
Well is this possible with C#???
I think no...
But I am confused :rolleyes:......
If yes please post a source code sample.
Thanks in advance.
 
Well let me explain to you.
Data modeling (a program of OcBible package) calculates some models.
On background loads 9 different threads simultaneously.
But they are:

Code:
private void exp_regression()
{
....
...
...
}

private void power_regression()
{
....
...
...
}

and so on.
Thus from main function (a button) I called them such as:

Code:
private void Compute_button_click(object sender, e SystemEventArgs)  
{
.....
.....
t1.Start();
t2.Start();
}

Thus the program performs the calculations.
If I want to add a stop button to cancel any calculation how can I do this???
Moreover the Exp (exponential regression) and the Power regression use some global variables cos I don't know how can I call a non void function using a "thread style" statement (in C# of course).
Anyway if you still don't understand me I will post other day the whole code to be more specific.
But inform me.
 
Last edited:
Of course you can pass parameters into threads. To my limited knowledge (i usually use the thread pool and not create my own thread) there are three ways:
  • Locked class level variables -> Not very elegent but will do the job. If you start getting weird bugs probably due to the fact you have not locked everything down.
  • Delegates -> You can create your own delegate (with parameters) and call BeginInvoke on it. This will cause .Net to kick off the given method (delegate is a pointer to a method) on a new thread. If you want to cancel you will need to have a locked variable that other threads can signal and then in the called method it will check this at various stages.
  • Own thread -> I don't believe that you cant start a thread with out parameters; thats not something MS would have overlooked. As said, its not my strength but I do believe it can be done.

There are some great articles out there, one of which shows async delegates in action while trying to calculate pie to a huge number of places - and includes code to cancel.
 
Thank you. But I must be more specific.
Here is my source code.

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsApplication1
{
    public partial class Form1:Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Thread t1,t2;   
        int x,y,result1,result2;
        private void btn_Fire_Click(object sender,EventArgs e)
        {
            Random k=new Random();
            x=k.Next(50);
            y=k.Next(60);
            t1=new Thread(new ThreadStart(Linear));
            t2=new Thread(new ThreadStart(Power));
            t1.Start();
            t2.Start();
            System.Threading.Thread.Sleep(0);
            label1.Text=result1.ToString();
            label2.Text=result2.ToString();
        }
        private void btn_Stop_Click(object sender,EventArgs e)
        {
            t1.Abort();	 // The stop button terminates the running threads if the user
            t2.Abort();     // press it in case of long calculation time (for example).
        }
        private void Linear()
        {
            // Assume that the procedure (and the next one) performs many complex calculations
            // which are completed after a long time but not always.
            result1=x+x;          
        }
        private void Power()
        {
            result2=y*y;           
        }
    }
}

How we can convert it????

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsApplication1
{
    public partial class Form1:Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void btn_Fire_Click(object sender,EventArgs e)
        {
            int x,y;
            int result1,result2;
            Random k=new Random();
            x=k.Next(50);
            y=k.Next(60);
                        
           /*
	Here is the problem........
                How can I call the 2 threads, passing the x,y parameters 
                and the return value of 2 threads to be stored in variables
                result1, result2 correspondingly????????
           */

            System.Threading.Thread.Sleep(0);     
            label1.Text=result1.ToString();
            label2.Text=result2.ToString();
        }
        private void btn_Stop_Click(object sender,EventArgs e)
        {
        	// How we can terminate the running threads????
        }
        private int Linear(int x)
        {
            // .......... complex calculations
            return x+x;          
        }
        private int Power(int y)
        {
            //....... complex calculations	
            return y*y;           
        }
    }
}
 
Right I will tell you how I would do it (assuming I've understood what you were asking). First create a delegate:
Code:
private delegate double MethodToCall(int input);
Next create two objects that point at the methods you want (remember they will have to have the same input and outputs as the delegate!):
Code:
MethodToCall callLinear = new MethodToCall(Linear);
MethodToCall callPower = new MethodToCall(Power);
Next create a method to update your form - remember to update the form only from the same thread that the form was created on:
Code:
        private void UpdateForm(IAsyncResult myData)
        {
            if (myData.IsCompleted)
            {
                if (this.InvokeRequired)
                    this.Invoke(new MethodInvoker(delegate() { UpdateForm(myData); }));
                else
                {
                    // Get a handle on the original delegate and get the results.
                    MethodToCall bob = ((AsyncResult)myData).AsyncDelegate as MethodToCall ;
                    label7.Text = bob.EndInvoke(myData).ToString();
                }
            }
        }
Finally you need to kick everything into action with the following (remember this will execute the methods that the delegate points to on a thread from the thread pool and then automatically call the UpdateForm method when finished):
Code:
callLinear.BeginInvoke(variableToPass, new AsyncCallback(UpdateForm), null);
callPower.BeginInvoke(variableToPass, new AsyncCallback(UpdateForm), null);
Pretty sure thats what you were asking for. If not - well I'm spent :}
 
First of all I must express my great thanks to you Goksly and for Bradzac, JakeG (Overclockers Australia members) for helping me.
I created the same thread there but OCAU is not viewable for guests thus I am posting here my ideas.
Moreover I must clarify that I am not a professional programmer! I just program for OcBible.
Anyway for newbies like me one solution is the following:

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

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

        delegate int MethodToCall(int i,int j);
        BackgroundWorker myWorker1,myWorker2;
                                
        private void btn_Fire_Click(object sender,EventArgs e)
        {
            int result=0;
            myWorker1=new BackgroundWorker();
            myWorker2=new BackgroundWorker();
            myWorker1.DoWork+=new DoWorkEventHandler(delegate
            {
                MethodToCall callLinear=new MethodToCall(Linear);
                result=callLinear.Invoke(3,5);  // Here result=8 
            });
            myWorker2.DoWork+=new DoWorkEventHandler(delegate
            {
                MethodToCall callPower=new MethodToCall(Power);
                callPower.Invoke(4,7);
            });
            myWorker1.RunWorkerAsync();
            myWorker2.RunWorkerAsync();
            // If we add a statement e.g. MessageBox.Show("result="+result.ToString()); the value is always 0
            
            //......
            //......  More statements which use the result parameter such as
            //......  if-else conditions thus the parameter mush have the actual value
            //......
        }  
        private int Linear(int i,int j)
        {
            for (int k=0; k<=100; k++)  // 2 progress bars added just to show
            {                                         // that 2 threads are running during a session
                Thread.Sleep(2);           // BTW this statement spends CPU time (assume complex calculations)
                progressBar1.Value=k;
            }
            return i+j;
        }
        private int Power(int i,int j)
        {
            for (int k=0; k<=100; k++)
            {
                Thread.Sleep(3);
                progressBar2.Value=k;
            }
            return i*j;
        }
    }
}

As you understand the code is a hybrid of Goksly's and JakeG's ideas.

Hopefully the source code:
1) Passes parameters in threads. Not only one like PaParameterizedThreadStart (damn we need type casting as Bradzac posted at OCAU).
2) Loads 2 (similarly more) threads during a session.
3) Threads return a value (if we want).
Unfortunately the source code:
1) We cannot set thread priority. This is useful if a program loads many of them --> thus we can manage which of them are running first etc......
2) The result parameter has wrong value outside of the delegate block.


Apart of the disadvantages if we don't care for priorities and returnable values (a void function for example) this is the best solution IMHO.
This page here covers many topics thank you W1zzard (TechPowerUp!) & AndyCosmonaut (OCAU) for the link.
Here it is:

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

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

        Thread t1,t2;

        private void btn_Fire_Click(object sender,EventArgs e)
        {
            double dummy=2310.2003;   // OcBible's forbidden number!!!!!
            Approximation regression1=new Approximation(2,3,4);
            Approximation regression2=new Approximation(2,3,(int) dummy);
            t1=new Thread(new ThreadStart(regression1.Linear));
            t2=new Thread(new ThreadStart(regression2.Power));
            t1.Priority=ThreadPriority.BelowNormal;
            t2.Priority=ThreadPriority.BelowNormal;
            t1.Start();
            t2.Start();
            int result1=regression1.result1;
            int result2=regression2.result2;
            
            //......
            //......  More statements which use the result1,result2 parameters such as
            //......  if-else conditions thus the parameter mush have the actual value
            //......	
        }
        private void btn_Stop_Click(object sender,EventArgs e)
        {
            t1.Abort();
            t2.Abort();
        }
    }
    public class Approximation
    {
        private int i,j,k;
        public int result1,result2;  

        public Approximation(int i,int j,int k)
        {
            this.i=i;
            this.j=j;
            this.k=k;
        }			// The first procedure uses 3 variables but the second 2 that's why I used
        public void Linear()         // above the dummy variable. Of course I could write one more public class
        {                                      // but this sucks LOL (never waste time) 
            for (long m=-90000000; m<=500000000; m++)
                    ; // This statement spends CPU time (assume complex calculations).....
            result1=i+j+k;
        }
        public void Power()
        {
            for (long m=-900000000; m<=90000000; m++)
                    		; 
            result2=i*j;
        }
    }
}

Hopefully the source code:
1) Passes parameters in threads.
2) Loads many threads during a session.
3) Threads return a value.
4) We can play with thread priority property.
Unfortunately the source code:
The result1, result2 parameters has wrong values again!

-->Therefore:
How we can manage the above source codes to get the actual values for the parameters?
One solution is to increase t1 & t2 priorities to Highest (for the second source code) but CPU load will be heavy so the stop button does not respond to terminate the running threads.
Any other ideas???????? :rolleyes:
 
I had a while loop that was doing some pretty easy calculations and that resulted in it hanging the GUI. To combat this I put a 10ms Sleep every 20 loops. I think you could do the same thing; set the thread priority to the highest and then have a sleep in there to allow the CPU to go and do other things (i.e. stop the GUI from hanging).

I must admit I'm slightly confused as to why you are having wrong parameter values; have you done some debugging to see where things are going wrong? Ultimately I would say go with my original version (:P) but use proper methods instead of anonymous delegates and get the value from call back object. I've never had an issue with that way of doing things. As explained earlier, not really used threads much - unless you are going to be spawning many (read > 10), I don't see why you would want to handle it yourself when the framework will do it via the threadpool.
 
I think you're getting incorrect results because you're not waiting for the thread to complete before you access the return value?

Code:
t1.Start();
t2.Start();

[COLOR="YellowGreen"]// Need to wait for the thread to complete here, or 
// better still get the thread to notify you when it 
// has finished.[/COLOR]

int result1=regression1.result1;
int result2=regression2.result2;
 
Last edited:
set the thread priority to the highest and then have a sleep in there
I will try this but the stop button will respond immediately? :rolleyes: I will see.
I think you're getting incorrect results because you're not waiting for the thread to complete before you access the return value?
I knew this mate that's why I asked how we can get the correct values waiting threads completeness
 
Another way, not sure if mentioned not got time to read all this, but if u fussed about response use the thread pool, pass in an object and then typecast it in the routine.
 
I knew this mate that's why I asked how we can get the correct values waiting threads completeness

Apologies, it just wasn't clear that you knew why you were getting the wrong results.

Goksly has posted what looks to be a sensible solution, but otherwise try the following which makes use of the BackgroundWorker class, and allows for elegant cancellation of the background threads.

Code:
	private BackgroundWorker _backgroundWorker1 = new BackgroundWorker();
	private BackgroundWorker _backgroundWorker2 = new BackgroundWorker();

	private bool _worker1Finished = false;
	private bool _worker2Finished = false;

	private void StartButton_Click(object sender, EventArgs e)
	{
		_worker1Finished = false;
		_worker2Finished = false;

		_backgroundWorker1.WorkerSupportsCancellation = true;
		_backgroundWorker2.WorkerSupportsCancellation = true;

		_backgroundWorker1.DoWork += new DoWorkEventHandler(BackgroundWorker1_DoWork);
		_backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorker_RunWorkerCompleted);

		_backgroundWorker2.DoWork += new DoWorkEventHandler(BackgroundWorker2_DoWork);
		_backgroundWorker2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BackgroundWorker_RunWorkerCompleted);

		_backgroundWorker1.RunWorkerAsync(10);
		_backgroundWorker2.RunWorkerAsync(7);
	}

	private void CancelButton_Click(object sender, EventArgs args)
	{
		_backgroundWorker1.CancelAsync();
		_backgroundWorker2.CancelAsync();
	}

	void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs args)
	{
		int max = (int)args.Argument;
		int i = 0;

		while (i++ < max && _backgroundWorker1.CancellationPending == false)
		{
			[COLOR="YellowGreen"]// Do something time consuming.[/COLOR]

			Thread.Sleep(1000);

			args.Result = Environment.TickCount;
		}

		if (_backgroundWorker1.CancellationPending == true)
		{
			args.Cancel = true;
		}
	}

	void BackgroundWorker2_DoWork(object sender, DoWorkEventArgs args)
	{
		int max = (int)args.Argument;
		int i = 0;

		while (i++ < max && _backgroundWorker2.CancellationPending == false)
		{
			[COLOR="yellowgreen"]// Do something time consuming.[/COLOR]

			Thread.Sleep(1000);

			args.Result = Environment.TickCount;
		}

		if (_backgroundWorker2.CancellationPending == true)
		{
			args.Cancel = true;
		}
	}

	void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs args)
	{
		if (args.Cancelled)
		{
			MessageBox.Show("Cancelled");
		}
		else if (args.Error != null)
		{
			MessageBox.Show(args.Error.Message);
		}
		else
		{
			if (sender == _backgroundWorker1) _worker1Finished = true;
			if (sender == _backgroundWorker2) _worker2Finished = true;

			if (_worker1Finished && _worker2Finished)
			{
				MessageBox.Show("Both threads completed");
			}
		}
	}
 
The first one (using BackgroundWorker). :)
If a program runs 1-2 threads (not simultaneously always) I prefer to use ThreadStart and one external variable in class if the threads return values.
 
Last edited:
Back
Top Bottom