2

I have a Windows Forms application at the moment, and I want to create a new thread and run a method on another class that accepts an input.

For example

public partial class Form1: Form {
    SerialPort serialInput;
    // I want to create a new thread that will pass the parameter serialInput into the method
    // SMSListener on another class and run the method contionously on the background.
}

class SMS
{
    public void SMSListener(SerialPort serial1)
    {
        serial1.DataReceived += port_DataRecieved;
    }

    private void port_DataRecieved(object sender, SerialDataReceivedEventArgs e)
    {
        // Other codes
    }
}

How do I perform this in C#? I have seen numerous examples on the web, and most of them run the method on the same class with no parameters, but none that suits my requirements.

Jakob Möllås
  • 4,239
  • 3
  • 33
  • 61
abduls85
  • 548
  • 8
  • 15
  • 2
    Have a look at [BackgroundWorker Class](http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx) – digEmAll May 17 '11 at 08:35
  • Already tried that but still figuring out on how to get my desired result. – abduls85 May 17 '11 at 08:43

3 Answers3

4

Perhaps a Background Worker could help you?
It is a bit hard to understand what you are aiming at.

public class Runner
{
    private readonly BackgroundWorker _worker = new BackgroundWorker();

    public Runner()
    {
        _worker.DoWork += WorkerDoWork;
    }

    public void RunMe(int payload)
    {
        _worker.RunWorkerAsync(payload);
    }

    static void WorkerDoWork(object sender, DoWorkEventArgs e)
    {
        var worker = sender as BackgroundWorker;

        while (true)
        {
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                break;
            }

            // Work
            System.Threading.Thread.Sleep((int)e.Argument);
        }
    }
}
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
Jakob Möllås
  • 4,239
  • 3
  • 33
  • 61
  • I have already tried Backgroundworker but i still have not figured out how to get it to work to achieved my desired result. Basically i want to run a new thread from my winform class that will pass the parameter serialInput into the SMS class method SMSListener. – abduls85 May 17 '11 at 08:41
  • Ok, why do you need to pass in the SMSListener class instance? To share state? This could lead to cross-threading issues. Please clarify a bit! – Jakob Möllås May 17 '11 at 08:43
  • Could it be that you want a thread reading data and then place it in a queue for the main thread to consume? I.e. a **producer/consumer pattern**? In this case a background worker clearly is not enough. [Have a look here](http://stackoverflow.com/questions/1371249/c-producer-consumer-pattern) for a discussion on producer/consumer. – Jakob Möllås May 17 '11 at 08:53
  • Thanks for all your help. Managed to solve the problem. My problem is a very complex producer and consumer issue. – abduls85 May 17 '11 at 09:00
2

I am not an expert on Multithreading but to the best of my knowledge you can only start threads on methods that accept an object parameter and return void. So in order to achieve that for your problem (don't shoot me down if there is a better approach!) I would do something like

public partial class Form1: Form {
    SerialPort serialInput;
    // I want to create a new thread that will pass the parameter serialInput into the method
    // SMSListener on another class and run the method contionously on the background.
    SMS sms = new SMS();
    Thread t = new Thread(sms.SMSListenerUntyped);
    t.Start(serialInput);
}

class SMS
{
    public void SMSListenerUntyped(object serial1) {
        if (serial1 is SerialPort) //Check if the parameter is correctly typed.
             this.SMSListener(serial1 as SerialPort);
        else
           throw new ArgumentException();
    }

    public void SMSListener(SerialPort serial1)
    {
        serial1.DataReceived += port_DataRecieved;
    }

    private void port_DataRecieved(object sender, SerialDataReceivedEventArgs e)
    {
        // Other code.
    }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nikhil
  • 3,304
  • 1
  • 25
  • 42
0

How about just use the ThreadPool directly with a anonymous method allowing you to access your surrounding locals?

    public void OnButtonClick(object sender, EventArgs e)
    {
        SerialPort serialInput = this.SerialInput;
        System.Threading.ThreadPool.QueueUserWorkItem(delegate
        {
            SmsListener listener = new SmsListener(serialInput);
        });
    }
Polity
  • 14,734
  • 2
  • 40
  • 40