I've been trying to pass an object to my main thread process but it seems it will not work in the way I thought it would.
First I create the Thread:
Thread thrUDP;
Then I create the object I will use to store the data I need:
UDPData udpData;
Now I Initialize the object withthe correct data, Set up the new thread and start it with the object passed into the Start() method:
udpData = new UDPData("224.5.6.7", "5000", "0", "2");
thrUDP = new Thread(new ParameterizedThreadStart(SendStatus));
thrUDP.Start(udpData);
This is the method I wish to start:
private void SendStatus(UDPData data)
{
}
I remember using Threads a while back and I'm sure they weren't so difficult to pass data to, am I doing this the wrong way or am I just missing a piece of code?
Thanks!
The ParameterizedThreadStart delegate is declared as:
public delegate void ParameterizedThreadStart(object obj);
Clearly, this delegate isn't compatible with your method's signature, and there isn't a direct way to get a System.Threading.Thread to work with an arbitrary delegate-type.
One of your options would be to use a compatible signature for the method, and cast as appropriate:
private void SendStatus(object obj)
{
UDPData data = (UDPData)obj;
...
}
The other option would be to punt the problem to the C# compiler, creating a closure. For example:
new Thread(() => SendStatus(udpData)).Start();
Do note that this uses the ThreadStart delegate instead. Additionally, you should be careful with subsequently modifying the udpData local, since it is captured.
Alternatively, if you don't mind using the thread-pool instead of spawning your own thread, you could use asynchronous delegates. For example:
Action<UDPData> action = SendStatus;
action.BeginInvoke(udpData, action.EndInvoke, null);
private void SendStatus(object data)
{
UDPData myData = (UDPData) data;
}
Related
how to convert my VB.net code to C#..?
I want to use a looping function with a thread.
VB.Net Code
For i As Integer = 0 To _port_count
Dim worker As New Threading.Thread(AddressOf looping)
worker.Start(_list(i))
commThread.Add(worker)
Next
public sub looping(Byvar PortList As PortList) 'looping function
C# Code
for (int i = 0; i <= _port_count; i++)
{
Thread worker = new Thread(looping);
worker.Start(_list[i]);
commThread.Add(worker);
}
public static void looping (PortList PortList) {}
but C# code didn't work. :(
thanks for your helps.
The Thread constructor will take either a ThreadStart delegate or a ParameterizedThreadStart delegate. The first has no parameters and the second has one parameter of type object. If you're using a named method then it has to match one of those two signatures, which yours does not. VB will allow you to do the wrong thing and attempt to clean up for you if it can but C# expects you to do the right thing yourself. These days, if you want to call a method whose signature does not match, you can use a Lambda with a matching signature instead, then call your method in that:
Thread worker = new Thread(() => looping(_list[i]));
worker.Start();
What's declaration of looping function ?
And some more info ?
Here is an example from Microsoft Docs.
using System;
using System.Threading;
public class Work
{
public static void Main()
{
// Start a thread that calls a parameterized static method.
Thread newThread = new Thread(Work.DoWork);
newThread.Start(42);
// Start a thread that calls a parameterized instance method.
Work w = new Work();
newThread = new Thread(w.DoMoreWork);
newThread.Start("The answer.");
}
public static void DoWork(object data)
{
Console.WriteLine("Static thread procedure. Data='{0}'",
data);
}
public void DoMoreWork(object data)
{
Console.WriteLine("Instance thread procedure. Data='{0}'",
data);
}
}
// This example displays output like the following:
// Static thread procedure. Data='42'
// Instance thread procedure. Data='The answer.'
link: https://msdn.microsoft.com/en-us/library/1h2f2459(v=vs.110)
Change you looping-method signature to following:
public static void looping (object PortList)
As documentation says, ParameterizedThreadStart passed as Thread constructor parameter has to be object.
I have the method that takes an argument from external dll through a delegate pointer:
public delegate void NotificationsCallbackDelegate(CinectorNotification message);
NotificationsCallbackDelegate notificationsCallbackDeleg;
IntPtr notificationsCallbackPointer;
notificationsCallbackDeleg = NotificationsCallback;
notificationsCallbackPointer = Marshal.GetFunctionPointerForDelegate(notificationsCallbackDeleg);
instance.SetNotificationsCallback(notificationsCallbackPointer);
private void NotificationsCallback(CinectorNotification notif)
{
Log.AppendText("[" + notif.timestamp + "] " + notif.type + ": " + notif.message + Environment.NewLine);
}
So, input argument 'message' is something that can be passed by dll at any time during the application flow, whenever the external engine generates some log. It is like an event.
I use the following code to put a method on a new thread:
private void startNotifications()
{
Thread NotificationsThread = new Thread(new ThreadStart(NotificationsCallback));
NotificationsThread.IsBackground = true;
NotificationsThread.Start();
}
However, the method NotificationsCallback(CinectorNotification notif) takes in an argument and therefore doesn't match the delegate for ThreadStart. So how would I put a method like this on a different thread?
You can use Task.Run and supply it a lambda where you call NotificationsCallback with whatever arguments you need For example:
private void startNotifications()
{
Task.Run(() => NotificationsCallback(arg1, arg2) );
}
This will result in NotificationsCallback being run on on a ThreadPool thread.
For more information on Task.Run, see: https://msdn.microsoft.com/en-us/library/hh195051(v=vs.110).aspx
You code would work if there is a method passed in the parameter is parameterless.
If you want a parametrised thread, you should use another overload of the Thread constructor which will take ParameterizedThreadStart.
Start method on the thread is then called with an argument which is passed on to the thread method like this:
Thread thread = new Thread(WorkerMethod);
thread.Start(35); //for example 35
void WorkerMethod(object parameter)
{
int? intParameter = parameter as int?; //for example
if (intParameter.HasValue)
{
//do stuff
}
}
You can also use Task, which is a more modern approach to multi-threading.
Task.Factory.StartNew(() => WorkerMethod(35)); //for example 35
Or Task.Run in .NET 4.5 and newer. In task one can pass as many paramaters as wanted (without creating a container for them) and also the parameters can be strongly typed... not just object.
Instead of using ThreadStart you could use ParameterizedThreadStart and pass the required parameters in Thread.Start.
I have the following method, which I want to run using WaitCallBack delegate (C# Thread-Pooling) technique:
public void ExportData(string data){
//Codes goes in here
}
how to use ThreadPool.QueueUserWorkItem(new WaitCallback(ExportData),object}
in order to call this method??
The WaitCallback that this function expects takes an object state parameter. So you could do this:
string data = "some data";
ThreadPool.QueueUserWorkItem(state => ExportData((string)state), data);
or update the signature of your method:
public void ExportData(object state)
{
string data = (string)state;
//Codes goes in here
}
and then:
string data = "some data";
ThreadPool.QueueUserWorkItem(ExportData, data);
Some options:
Declare the method with type string and cast
Use a lambda expression instead, e.g.
ThreadPool.QueueUserWorkItem(ignored => ExportData(value))
where I assume value is a string variable in scope at the time. This will create a new delegate instance each time you go through this code, to capture value.
A combination of the above:
ThreadPool.QueueUserWorkItem(x => ExportData((string) x), value)
This will (potentially) reuse the same delegate instance on every call, as the value is passed via the normal WaitCallback instead of being captured by the delegate.
Additionally, you might want to consider using the rather more modern Task API unless you're targeting an old version of .NET. It's a generally more pleasant way of scheduling and managing tasks.
How can I pass a Method2 to thread as shown in below if i write code as shown in below it shows an error Error
The best overloaded method match for
'System.Threading.Thread.Thread(System.Threading.ThreadStart)' has
some invalid arguments
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main Thread : ");
Thread obj = new Thread(Method2);
obj.Start();
Console.ReadLine();
}
private static int Method2(int a)
{
return a;
}
}
When i use the following code it works
Thread obj = new Thread(() => Method2(1));
But why it's not working when i pass delegate object
delegate int del(int i);
del d = Method2;
Thread obj = new Thread(d);
What is the difference between above 2 , in 1st case i used Lambda expression in second case directly passed delegate object is there any thing else?
The Thread constuctor takes two types of delegates, ThreadStart and ParameterizedThreadStart. To see what type of method these delegates accept you can create it and the constructor will show you, so for example,
var parameterMethod = new ParameterizedThreadStart(...
If you type the above you will see the delegate takes a function with one object as the parameter and returns void.
void (object) target
This is why your Method that takes an int will not work because the signature does not match the delegate target signature. When you wrap it in a lambada, you are actually passing in a method that takes no parameters and returns void, so the Method2 signature is not even looked at. Wrapping method calls with a lambada like this can be very useful for getting the signature to match.
delegate void del(object obj);
del d = () => Method2(1);
Thread obj = new Thread(d);
There is an infinite number of possible method signatures so Threads and Tasks keep it simple and say if you want to pass something, pass a single object. Since all types derive from object, this lets you pass in anything you want, then cast it later.
Try this:
Thread obj = new Thread(() => Method2(some_int_value));
I have a webservice method FetchNumber() that fetches a number from a database and then returns it to the caller. But just before it returns the number to the caller, it needs to send this number to another service so instantiates and runs the BackgroundWorker whose job is to send this number to another service.
public class FetchingNumberService : System.Web.Services.WebService
{
[WebMethod]
public int FetchNumber()
{
int value = Database.GetNumber();
AsyncUpdateNumber async = new AsyncUpdateNumber(value);
return value;
}
}
public class AsyncUpdateNumber
{
public AsyncUpdateNumber(int number)
{
sendingNumber = number;
worker = new BackgroundWorker();
worker.DoWork += asynchronousCall;
worker.RunWorkerAsync();
}
private void asynchronousCall(object sender, DoWorkEventArgs e)
{
// Sending a number to a service (which is Synchronous) here
}
private int sendingNumber;
private BackgroundWorker worker;
}
I don't want to block the web service (FetchNumber()) while sending this number to another service, because it can take a long time and the caller does not care about sending the number to another service. Caller expects this to return as soon as possible.
FetchNumber() makes the background worker and runs it, then finishes (while worker is running in the background thread). I don't need any progress report or return value from the background worker. It's more of a fire-and-forget concept.
My question is this. Since the web service object is instantiated per method call, what happens when the called method (FetchNumber() in this case) is finished, while the background worker it instatiated and ran is still running?
What happens to the background thread? When does GC collect the service object? Does this prevent the background thread from executing correctly to the end? Are there any other side-effects on the background thread?
Thanks for any input.
From what I see from your code I'd say that neither the Background worker, nor the instance of the AsyncUpdateNumber class gets collected as they reference each other and there is no code that breaks this circular reference.
The circular reference is created by the AsyncUpdateNumber class referencing the BackgroundWorker and registering an event with the BackgroundWorker creating a reference to the instance of the AsyncUpdateNumber class.
So what can you do ... consider using one of the following options instead of the BackgroundWorker:
Use a Thread.
Use BeginInvoke.
Use the ThreadPool.
Sample 1:
var thread = new Thread(new ParameterizedThreadStart((v) => { /* do stuff */ }));
thread.Start(value);
Sample 2:
var func = new Action<int>(v => { /* do stuff */ });
func.BeginInvoke(value, null, null);
Sample 3:
var threadProc = new Action<object>(v => { /* do stuff - note v is of tyoe object */ });
ThreadPool.QueueUserWorkItem(new WaitCallback(threadProc));
Edit:
To answer your question from the original post: The method executing the thread always runs until it is completed, irrespectively whether the method declaring it exits or not. Even the anonymous methods above will run until completed. The concept applied here is called a closure (AFAIK), in case of the anonymous methods it even keeps all referenced variables alive even if they are not declared within the method itself.
However, your class is a prime example of a circular reference that will only be reclaimed once the application process finishes. It's one of these more subtle things in .NET that - even in a managed system - can cause memory leaks ... events create strong references.
Although, in case of a single call this does not cause any problem, once you hit some calls more it might become a problem indeed.
Rewrite the single web method
[WebMethod]
public int FetchNumber()
{
int value = Database.GetNumber();
AsyncUpdateNumber async = new AsyncUpdateNumber(value);
return value;
}
as two with and an asynchronous delegate:
public delegate AsyncUpdateNumber GetAsyncUpdateNumber(object state, int value);
[WebMethod]
public IAsyncResult BeginFetchNumber(AsyncCallback cb, object state)
{
int value = Database.GetNumber();
AsyncUpdateNumber async = new AsyncUpdateNumber(value);
GetAsyncUpdateNumber getAsyncUpdateNumber = new GetAsyncUpdateNumber(async.DoLongRunningThing);
return getAsyncUpdateNumber.BeginInvoke(state, cb, getAsyncUpdateNumber);
}
[WebMethod]
public int EndFetchNumber(IAsyncResult res)
{
GetAsyncUpdateNumber getAsyncUpdateNumber = (GetAsyncUpdateNumber)res.AsyncState;
return getAsyncUpdateNumber.EndInvoke(res);
}
These will appear as a single web method called FetchNumber(). The BeginInvoke() in BeginFetchNumber() will execute asynchronously. I had to make up a method called DoLongRunningThing that's in AsyncUpdater for the delegate to execute. Move the task you're needing done async off of the constructor into this new method. Hope this helps.