ParameterizedThread in .NET 1.1

Had a problem where I wanted to run a function in a thread but it expected multiple params. So I went around making the ParameterizedThread Class which helped me to execute this method.

The Class:

Public Class ParameterizedThread

    Private m_Method As [Delegate]

    Public Sub New(ByVal inMethod As [Delegate])

        m_Method = inMethod

    End Sub

    Public Sub Start(ByVal ParamArray inArgs As Object())

        Dim threadClass As New InternalThreadClass(m_Method, inArgs)

        Dim thread As New Threading.Thread(AddressOf threadClass.RunThread)
        thread.Start()

    End Sub

    Private Class InternalThreadClass

        Private m_Args() As Object
        Private m_Method As [Delegate]

        Public Sub New(ByVal inMethod As [Delegate], ByVal ParamArray inArgs As Object())
            m_Method = inMethod
            m_Args = inArgs
        End Sub

        Public Sub RunThread()

            Try
                m_Method.DynamicInvoke(m_Args)
            Catch ex As Exception
                Throw ex
            End Try

        End Sub

    End Class

End Class

 

Usage Example:

To use this class we need to create a delegate for our method. Create a new ParameterizedThread class instance and call the start method with the params the function expects.

Private Delegate Sub DoNothingDelegate(ByVal inName as String, ByVal inAge as String)
Private Sub DoNothing(ByVal inName as String, ByVal inAge as String)
    ' Does Nothing :)
End Sub

This is our function we would like to call and pass in the params, to do so use the following:

Dim deleg as DoNothingDelegate = AddressOf DoNothing
Dim thr as new ParameterizedThread(deleg)
' Call start passing in our params
thr.Start("bob", 22)


Issues:

There is not much checking to make sure the params match the types expected in the method. It seems to work fine for my purposes but it could be totally wrong.

Once again thanks for reading and any feedback on whether or not this will work as expected in all cases would be appreciated.


Cheers

Stefan

Update 200711151238:

I changed the class so that the args were placed in an internal class which was then called in the new thread. I thought maybe without this the state could be lost. No sure but..

8 Comments

  • Hi Stefan,

    What you have done is fine for .NET 1.1. If you can use .NET 3.5 which will be released in a few weeks, I can help you redesign this in a better way using generics.

    The main issue with your approach is:
    a) No compile time type checking (ie errors at runtime).
    b) You need to create a delegate.
    c) Calling DynamicInvoke is about 50 times slower than directly invoking a delegate.

    Forgive me for using C#, but if you precompile my code it will work fine for you in VB. Lets say you have a method "mymethod" which takes an integer and a string as params, with my code you could start a thread like this:

    Thread t = ThreadUtil.Create(mymethod, 10, "Hello");
    t.Start();

    With this version, you do not need to first create a delegate, and if the params do not match the supplied method you will get a compile time error. Also, you will see I am directly invoking the method, not using DynamicInvoke which is 50x faster.

    I have defined action delegates supporting up to 7 arguments, and if you supply more than 7 args I have (like you) allowed you to supply a delegate and fall back on DynamicInvoke.

    Here is my code below. I hope this help your project:

    using System;
    using System.Linq;
    using System.Threading;

    public delegate void Action2(A a,B b);
    public delegate void Action3(A a,B b,C c);
    public delegate void Action4(A a,B b,C c,D d);
    public delegate void Action5(A a,B b,C c,D d,E e);
    public delegate void Action6(A a,B b,C c,D d,E e,F f);
    public delegate void Action7(A a,B b,C c,D d,E e,F f,G g);

    public static class ThreadUtil
    {
    public static Thread Create(Action action, A a)
    {
    return new Thread(() => action(a));
    }

    public static Thread Create(Action2 action, A a, B b)
    {
    return new Thread(() => action(a, b));
    }

    public static Thread Create(Action3 action, A a, B b, C c)
    {
    return new Thread(() => action(a, b, c));
    }

    public static Thread Create(Action4 action, A a, B b, C c, D d)
    {
    return new Thread(() => action(a, b, c, d));
    }

    public static Thread Create(Action5 action, A a, B b, C c, D d, E e)
    {
    return new Thread(() => action(a, b, c, d, e));
    }

    public static Thread Create(Action6 action, A a, B b, C c, D d, E e, F f)
    {
    return new Thread(() => action(a, b, c, d, e, f));
    }

    public static Thread Create(Action7 action, A a, B b, C c, D d, E e, F f, G g)
    {
    return new Thread(() => action(a, b, c, d, e, f, g));
    }

    public static Thread Create(Delegate action, params object[] args)
    {
    return new Thread(() => action.DynamicInvoke(args));
    }
    }

    Best wishes,

    David Taylor

  • Stefan,

    I am so sorry to have written my code to require .NET 3.5, which is silly as I realise the exact same thing works on .NET 2 with a couple of changes. Here is the library below written so you can use it in the exact same way with .NET 2.

    This will work perfectly from VB once compiled onto a DLL:

    using System;
    using System.Threading;

    public delegate void Action2(A a,B b);
    public delegate void Action3(A a,B b,C c);
    public delegate void Action4(A a,B b,C c,D d);
    public delegate void Action5(A a,B b,C c,D d,E e);
    public delegate void Action6(A a,B b,C c,D d,E e,F f);
    public delegate void Action7(A a,B b,C c,D d,E e,F f,G g);

    public static class ThreadUtil
    {
    public static Thread Create(Action action, A a)
    {
    return new Thread(delegate(){action(a);});
    }

    public static Thread Create(Action2 action, A a, B b)
    {
    return new Thread(delegate(){action(a, b);});
    }

    public static Thread Create(Action3 action, A a, B b, C c)
    {
    return new Thread(delegate(){action(a, b, c);});
    }

    public static Thread Create(Action4 action, A a, B b, C c, D d)
    {
    return new Thread(delegate(){action(a, b, c, d);});
    }

    public static Thread Create(Action5 action, A a, B b, C c, D d, E e)
    {
    return new Thread(delegate(){action(a, b, c, d, e);});
    }

    public static Thread Create(Action6 action, A a, B b, C c, D d, E e, F f)
    {
    return new Thread(delegate(){action(a, b, c, d, e, f);});
    }

    public static Thread Create(Action7 action, A a, B b, C c, D d, E e, F f, G g)
    {
    return new Thread(delegate(){action(a, b, c, d, e, f, g);});
    }

    public static Thread Create(Delegate action, params object[] args)
    {
    return new Thread(delegate(){action.DynamicInvoke(args);});
    }
    }

  • Hi Stefan,

    I just revised my VB, and if you compile my library you can use it from VB like shown below. Not that if you turn Option String On you will even get compile time checking! This way you:
    a) Do not need to create a delegate first.
    b) The compiler will tell you if the parameters you supply do not match the method.
    c) It will be 50x faster than using DynamicInvoke

    Here is the demo module from VB:

    Option Strict On
    Module MyModule

    Sub DoWork(ByVal a As Integer, ByVal b As Integer)
    Console.WriteLine(a + b)
    End Sub

    Sub Main()
    Dim t = ThreadUtil.Create(AddressOf DoWork, 10, 20)
    t.Start()
    Console.ReadLine()
    End Sub

    End Module

  • Thanks for that David very cool stuff. I never knew about using generics for something like that it is very interesting. The only thing is I am stuck with .NET 1.1 hehe. But what I have seen here has taught me alot and makes me want to use .NET 2.0/3.5 more often.


    Cheers

    Stefan

  • Yes it is very cool isn't it.

    The nice thing you will notice is that apart from needing to know generics to write my little library, when you are using the library from another C# or VB project you do not need to know anything about generics. In other words, the generics features are simply used behind the scenes. The other nice feature is that you dont even need to use delegates!

    I would argue that the resulting code is really easy for a beginner programmer to understand.

    The other thing is that if you try the VB code I supplied in Visual Studio 2005, you will notice if you try to supply a method and do not use the correct parameters, Visual Studio will give you the squiggly underneath the code indicating you have made an error (as long as you use Option Strict On. So you really do have compile time checking and verification via intellisense.

    Note: Microsoft is also just about to release a CTP of an updated threading framework after they release .NET 3.5 in 2 weeks. The framework will probably not be released until .NET 4, but the first CTP will be released soon. It will provide a much simpler model for doing threading than we have today, and also make it easier to do things like return a value from a running thread to your main thread. It will be in a namespace called System.Parallel and the main feature is System.Parallel.Task

    Try to move your employer over to .NET 2 if at all possible ;-)

    Regards,

    David

  • Thanks mate good info. I will be pushing for a move to .net 3.5 but I am just stuck on an old app atm :P. If you have any links on this new framework can you email me: stefan.sedich@gmail.com


    Thanks

    Stefan

  • Is possible that ParameterizedThread is only available for visual studio 2005? I'm using vs 2003 and I can only use "Thread" standard, without parameters... can somebody help me? Thanks!

  • urix,

    You need to include my class if using VS 2003 and .net 1.1.


    Cheers

Comments have been disabled for this content.