0

I use the code below to run a thread with multiple parameters:

public Thread StartTheThread(System.Windows.Threading.Dispatcher dispatcher, int param1, string param2)
{
    Thread t = new Thread(() => Work(Maingrid.Dispatcher, param1, param2));
    t.Start();
    return t;
}

public delegate void delegate1(Color randomparam, Color secondparam);

public void Work(System.Windows.Threading.Dispatcher dispatcher, int param1, string param2)
{
    dispatcher.Invoke(new delegate1(update), {Color.FromRgb(255, 255, 0),Color.FromRgb(170, 255, 170)});
}

public void update(Color randomparam, Color secondparam)
{
    ...
}

Creating a new thread normally requires either "ThreadStart" or "ParameterizedThreadStart" method. Threadstart method is for threads with no parameter, and parameterizedthreadstart method is for threads with only 1 parameter (as object). But I have different types of parameters. Since these methods are delegates, I tried to store the thread using a custom delegate to call later on:

public delegate void starterdelegate(System.Windows.Threading.Dispatcher dispatcher, int param1, string param2);

public Thread StartTheThread(int param1, string param2)
{
    Thread t = new Thread(new starterdelegate(RealStart));
    ...
    return t;
}

But in this case, compiler returns this error:

"Overload resolution failed because no accessible 'New' can be called with these arguments: 'Public Sub New(start As System.Threading.ParameterizedThreadStart)': Value of type 'ThreadTraining.MainWindow.starterdelegate' cannot be converted to 'System.Threading.ParameterizedThreadStart'. 'Public Sub New(start As System.Threading.ThreadStart)': Value of type 'ThreadTraining.MainWindow.starterdelegate' cannot be converted to 'System.Threading.ThreadStart'."

What I mean is that there's no problem with running thread with multiple parameters, but when I want to store the thread t, I don't want to submit parameters because they will be changed until next time I run the thread. If I use ParameterizedThreadStart method and don't submit parameters, compiler will throw a signature error. If I don't use one of the methods required, compiler will throw an overload resolution fail error.

I don't even know why this:

Thread t = new Thread(() => Work(Maingrid.Dispatcher, param1, param2));

works in first place. How is parameter of the "new Thread" here compatible with the methods required? I found this line of code on this page: https://stackoverflow.com/a/1195915/2770195

Any advice?

Community
  • 1
  • 1
MuhsinFatih
  • 1,891
  • 2
  • 24
  • 31
  • 1
    delete all that and use `async/await`. Also, whatever you're doing you should be using DataBinding. – Federico Berasategui Jun 30 '15 at 05:17
  • 1
    I don't really get what is it you want to achieve. – Ondrej Janacek Jun 30 '15 at 05:30
  • @HighCore What do you mean? I didn't understand. – MuhsinFatih Jul 02 '15 at 12:58
  • @OndrejJanacek I just don't want to submit parameters in order to store them. Why would I need to? It will just consume more redundant ram space (since I am definitely sure that it's parameters will change before next time I run them). For this reason, I feel like I am doing it wrong. There must be a better way – MuhsinFatih Jul 02 '15 at 13:05

3 Answers3

0

Use ParameterizedThreadStart Delegate. Refer here:

https://msdn.microsoft.com/en-us/library/system.threading.parameterizedthreadstart(v=vs.110).aspx

I think you should create a new class to encapsulate your parameters, and send the new class instance to thread as parameter.

Hope this help.

hungndv
  • 2,121
  • 2
  • 19
  • 20
  • This seems to simplify the parameters, thanks. But I still don't understand why I can't just store a thread with multiple parameters, since I can actually run a thread with multiple parameters. However, this is a good solution too. – MuhsinFatih Jul 02 '15 at 13:45
  • As I know so far, can't pass many (more than 1 parameter) to thread. Additionally, wrapping your parameters into an object is a best practice. Let think if you have 15 arguments need to pass to an function, you must carefully stare them to correct their positions... – hungndv Jul 02 '15 at 13:58
  • I used to wrap my parameters into an array, but yeah, like you said; when I have like 15 parameters, it's hard to remember their positions in the array. Creating class seems much more convenient. – MuhsinFatih Jul 02 '15 at 15:16
  • I will create a custom 'Params' which holds auto properties such as Param1, Param2,... In processing method of Thread, I will cast object to 'Params'. So the best practices are only suggested. So follow or not is up to you. :) – hungndv Jul 02 '15 at 15:21
  • Ok, thanks :) I wish I could mark your answer helpful, but I don't have enough reputation points to do that yet. I will mark this as helpful when I can. – MuhsinFatih Jul 02 '15 at 16:10
0

You can encapsulate the parameters in a class, but you can encapsulate also your logic in the class:

public class FooProcessor
{
    private readonly Color _color1;
    private readonly Color _color2;

    public FooProcessor(Color color1, Color color2)
    {
        _color1 = color1;
        _color2 = color2;
    }

    public Task ProcessAsync()
    {
        return Task.Run((Action) Process);
    }

    private void Process()
    {
        //add your logic here
    }
}

OT: if you don't have specific reason to use Thread instead of Task, use Task. Some older tutorials use Threads, because Task didn't exist at that time.

Liero
  • 25,216
  • 29
  • 151
  • 297
  • This seems to work, thanks. So each time I will overwrite the FooProcessor with new parameters and call ProcessAsync(). But I have a question. I have a ton of processes (thread, task whatever it will be) that have possibility to be run all at the same time and all must be able to controlled (suspended, overwritten, aborted etc.) individually and their parameters change over time. (next comment): – MuhsinFatih Jul 02 '15 at 13:32
  • Do you think this is the best way to store them? I mean, does creating a class of parameters with the process logic inside and creating a class of parameters referencing the process logic from main thread differ in the matter of speed and ram consume? All my threads have the same logic. (Note: I had my comment split into two parts because stackoverflow didn't let me type that long) – MuhsinFatih Jul 02 '15 at 13:32
  • For each process you have to create new instance of FooProcessor. its very important. If you have ton of processes, that you should not use thread, but task. You can use also `Parallel.Foreach` https://msdn.microsoft.com/en-us/library/dd460720(v=vs.110).aspx – Liero Jul 02 '15 at 13:38
  • I mean, does including the process logic inside the class affect performance? I have a long code and I wonder if the program will store the Process() void individually for each FooProcessor – MuhsinFatih Jul 02 '15 at 15:32
0

On SO there was an answer on this question about passing multiple parameters to ThreadStart method. I love this one:

    static void Main(string[] args)
    {
        for (int i = 1; i < 24; i++)
        {
            Thread t = new Thread( ()=>ThreadWorkingStuff(i,"2"+i.ToString() ));
            t.Start();
        }
        Console.ReadKey();
    }

    static void ThreadWorkingStuff(int a, string b)
    {
        Console.WriteLine(string.Format("Thread{2}|  a={0} b={1}", a, b, Thread.CurrentThread.ManagedThreadId));
    }