Is it unsafe to use local variables in a call to begininvoke - c#

I have to take over the source code of a bigger application from my colleaque that is written in C#. It uses windows forms an threads and right now it works as it should.
But one thing I am not sure about, is the way he handled parameters that are used in delegates that are raised from the thread to the windows forms in the application. I don't know why, but he defined many different object arrays with varying number of elements, eg:
private object[] delegateArray1;
private object[] delegateArray3;
private object[] delegateArray3A;
and in the code he used it then
delegateArray1 = new object[1]; // in the constructor of the thread class
delegateArray3 = new object[3];
delegateArray3a = new object[3];
// and this somewhere in the thread loop
delegateArray3[0] = systemtests.FehlerText;
delegateArray3A[1] = CheckState.Unchecked;
delegateArray3A[2] = testKanal;
sender.BeginInvoke(merkerInfoDelegate, delegateArray3);
whereby sender is the containercontrol from which the thread has been created.
merkerInfoDelegate points to a method with the signature
public void InfoAnzeige(string scrollText, CheckState state, int kanal);
The first question that I have:
Is it possible that my variables / objects that I pass to the BeginInvoke method are being garbage collected and thus are invalid when the delegate method gets finally executed. When yes, how do I prevent this from happen?
Is it not possible to call the delegate like this:
sender.BeginInvoke(merkerInfoDelegate, systemtests.FehlerText, CheckState.Unchecked, testKanal);
I would like to make the code more readable, more safe and more reliable. I think of declaring classes like the class MouseEventArgs, that consist of these parameters and that encapsulate all necessary data to be passed to the delegate method in the windows forms class...
public InfoDelegateEventArgs
{
public String Fehlertext;
public CheckState state;
public int Kanal;
}
this could be used like this:
idea = new InfoDelegateEventArgs(){...};
sender.BeginInvoke(merkerInfoDelegate, idea);

It is safe to pass "local" variables but remember they are no longer "local" once you pass them. The references have now been passed off to another operation that may be running concurrently on a separate thread. Now multiple threads have access to the "local" variable and thus it might require locking or other thread-safe treatment.
You don't need to worry about it being GC'd because there is still a reference that was passed to BeginInvoke.

Related

Is it possible to modify an object passed like a parameter to other thread with C#? [duplicate]

is there any way in c# to put objects in another thread? All I found is how to actually execute some methods in another thread. What I actually want to do is to instanciate an object in a new thread for later use of the methods it provides.
Hope you can help me,
Russo
Objects do not really belong to a thread. If you have a reference to an object, you can access it from many threads.
This can give problems with object that are not designed to be accessed from many threads, like (almost all) System.Windows.Forms classes, and access to COM objects.
If you only want to access an object from the same thread, store a reference to the thread in the object (or a wrapping object), and execute the methods via that thread.
There seems to be some confusion about how threads work here, so this is a primer (very short too, so you should find more material before venturing further into multi-threaded programming.)
Objects and memory are inherently multi-thread in the sense that all threads in a process can access them as they choose.
So objects do not have anything to do with threads.
However, code executes in a thread, and it is the thread the code executes in that you're probably after.
Unfortunately there is no way to just "put an object into a different thread" as you put it, you need to specifically start a thread and specify what code to execute in that thread. Objects used by that code can thus be "said" to belong to that thread, though that is an artificial limit you impose yourself.
So there is no way to do this:
SomeObject obj = new SomeObject();
obj.PutInThread(thatOtherThread);
obj.Method(); // this now executes in that other thread
In fact, a common trap many new multi-thread programmers fall into is that if they create an object in one thread, and call methods on it from another thread, all those methods execute in the thread that created the object. This is incorrect, methods always executes in the thread that called them.
So the following is also incorrect:
Thread 1:
SomeObject obj = new SomeObject();
Thread 2:
obj.Method(); // executes in Thread 1
The method here will execute in Thread 2. The only way to get the method to execute in the original thread is to cooperate with the original thread and "ask it" to execute that method. How you do that depends on the situation and there's many many ways to do this.
So to summarize what you want: You want to create a new thread, and execute code in that thread.
To do that, look at the Thread class of .NET.
But be warned: Multi-threaded applications are exceedingly hard to get correct, I would not add multi-threaded capabilities to a program unless:
That is the only way to get more performance out of it
And, you know what you're doing
All threads of a process share the same data (ignoring thread local storage) so there is no need to explicitly migrate objects between threads.
internal sealed class Foo
{
private Object bar = null;
private void CreateBarOnNewThread()
{
var thread = new Thread(this.CreateBar);
thread.Start();
// Do other stuff while the new thread
// creates our bar.
Console.WriteLine("Doing crazy stuff.");
// Wait for the other thread to finish.
thread.Join();
// Use this.bar here...
}
private void CreateBar()
{
// Creating a bar takes a long time.
Thread.Sleep(1000);
this.bar = new Object();
}
}
All threads can see the stack heap, so if the thread has a reference to the objects you need (passed in through a method, for example) then the thread can use those objects. This is why you have to be very careful accessing objects when multi-threading, as two threads might try and change the object at the same time.
There is a ThreadLocal<T> class in .NET that you can use to restrict variables to a specific thread: see http://msdn.microsoft.com/en-us/library/dd642243.aspx and http://www.c-sharpcorner.com/UploadFile/ddoedens/UseThreadLocals11212005053901AM/UseThreadLocals.aspx
Use ParameterizedThreadStart to pass an object to your thread.
"for later use of the methods it provides."
Using a class that contains method to execute on new thread and other data and methods, you can gain access from your thread to Data and methods from the new thread.
But ... if your execute a method from the class, you are executing on current thread.
To execute the method on the new thread needs some Thread syncronization.
System.Windows.Forms.Control.BeginInvoke do it, the Control thread is waiting until a request arrives.
WaitHandle class can help you.
There's a lot of jargon around threading, But it boils down something pretty simple.
For a simple program, you have one point of execution flowing from point a to b, one line at a time. Programming 101, right?
Ok, for multithreading, You now have more then one point of execution in your program. So, point 1 can be in one part of your program, and point 2 can be someplace else.
It's all the same memory, data and code, but you have more then one thing happening at a time. So, you can think, what happens of both points enter a loop at the same time, what do you think would happen? So techniques were created to keep that kind of issue either from happening, or to speed up some kind of process. (counting a value vs. say, networking.)
That's all it really is. It can be tricky to manage, and and it's easy to get lost in the jargon and theory, but keep this in mind and it will be much simpler.
There are other exceptions to the rule as always, but this is the basics of it.
If the method that you run in a thread resides in a custom class you can have members of this class to hold the parameters.
public class Foo
{
object parameter1;
object parameter2;
public void ThreadMethod()
{
...
}
}
Sorry to duplicate some previous work, but the OP said
What I actually want to do is to instanciate an object in a new thread for later use of the methods it provides.
Let me interpret that as:
What I actually want to do is have a new thread instantiate an object so that later I can use that object's methods.
Pray correct me if I've missed the mark. Here's the example:
namespace silly
{
public static class Program
{
//declared volatile to make sure the object is in a consistent state
//between thread usages -- For thread safety.
public static volatile Object_w_Methods _method_provider = null;
static void Main(string[] args)
{
//right now, _method_provider is null.
System.Threading.Thread _creator_thread = new System.Threading.Thread(
new System.Threading.ThreadStart(Create_Object));
_creator_thread.Name = "Thread for creation of object";
_creator_thread.Start();
//here I can do other work while _method_provider is created.
System.Threading.Thread.Sleep(256);
_creator_thread.Join();
//by now, the other thread has created the _method_provider
//so we can use his methods in this thread, and any other thread!
System.Console.WriteLine("I got the name!! It is: `" +
_method_provider.Get_Name(1) + "'");
System.Console.WriteLine("Press any key to exit...");
System.Console.ReadKey(true);
}
static void Create_Object()
{
System.Threading.Thread.Sleep(512);
_method_provider = new Object_w_Methods();
}
}
public class Object_w_Methods
{
//Synchronize because it will probably be used by multiple threads,
//even though the current implementation is thread safe.
[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
public string Get_Name(int id)
{
switch (id)
{
case 1:
return "one is the name";
case 2:
return "two is the one you want";
default:
return "supply the correct ID.";
}}}}
Just like to elaborate on a previous answer. To get back to the problem, objects and memory space are shared by all threads. So they are always shared, but I am assuming you want to do so safely and work with results created by another thread.
Firstly try one of the trusted C# patterns. Async Patterns
There are set patterns to work with, that do transmit basic messages and data between threads.
Usually the one threat completes after it computes the results!
Life threats: Nothing is fool proof when going asynchronous and sharing data on life threats.
So basically keep it as simple as possible if you do need to go this route and try follow known patterns.
So now I just like to elaborate why some of the known patters have a certain structure:
Eventargs: where you create a deepcopy of the objects before passing it. (It is not foolproof because certain references might still be shared . )
Passing results with basic types like int floats, etc, These can be created on a constructor and made immutable.
Atomic key words one these types, or create monitors etc.. Stick to one thread reads the other writes.
Assuming you have complex data you like to work with on two threads simultaneously a completely different ways to solve this , which I have not yet tested:
You could store results in database and let the other executable read it. ( There locks occur on a row level but you can try again or change the SQL code and at least you will get reported deadlocks that can be solved with good design, not just hanging software!!) I would only do this if it actually makes sense to store the data in a database for other reasons.
Another way that helps is to program F# . There objects and all types are immutable by default/ So your objects you want to share should have a constructor and no methods allow the object to get changed or basic types to get incremented.
So you create them and then they don't change! So they are non mutable after that.
Makes locking them and working with them in parallel so much easier. Don't go crazy with this in C# classes because others might follow this "convention' and most things like Lists were just not designed to be immutable in C# ( readonly is not the same as immutable, const is but it is very limiting). Immutable versus readonly

Is locking or Interlocked.Exchange required to swap a reference type field which is used in an other thread?

I know that there are .NET collections which are thread safe which I could use, but I still want to understand the following situation:
I have a Buffer class (below) which is used to writer data from a different thread, in a update loop interval (game) the main thread handles the data by swaping the list instance (to prevent both threads acting on the same instance at the same time).
So there is only a single additional thread who uses the "writerData" list, everything else is done on the main thread, but im not sure if the Swap method is thread "safe", because after searching for a while everyone seems to have a different opinion about swapping reference fields.
Some say that swapping reference doesn't require any locking other say that Interlocked.Exchange must be used in this case and other say it's not required, other say that the field must be violate and other say the keyword is "evil".
I know that threading is a difficult topic and maybe the other questions were too broad, but can someone help me to understand if any/which kind of "locking" is required in my specific case in the Swap method?
public class Buffer
{
List<byte> readerData;
List<byte> writerData; // This is the only field which is used by the other thread (by calling the Add method), well and by the Swap method, which is called from the main thread
// This method is only called by the other thread and it's the only method which is called from there
public void Add(byte data)
{
writerData.Add(data);
}
// Called on the main thread, before handling the readerData
public void Swap()
{
var tmp = readerData;
readerData = writerData
writerData = tmp;
}
// ... some other methods (which are only called from the main thread) to get the data from the (current) readerData field after calling the Swap method
}

Do I need to synchronize access the method arguments and locals when calling a method concurrently?

I have been writing a lot of code with static classes/methods that I believe will be called/executed simultaneously by multiple threads. So I am doing a lot of locking in my methods. I typically do this:
public static class MyThreadsafeMethods {
private static Object staticLock1 = new Object();
private static Object staticLock2 = new Object();
public static string StaticMethod1(string param1, int param2) {
lock (staticLock1) {
var _param1 = param1;
var _param2 = param2;
//highly confidential business logic here
return StaticMethod2(_param1, "Integer: " + _param2.ToString());
}
}
public static string StaticMethod2(string param1, string param2) {
lock (staticLock2) {
var _param1 = param1;
var _param2 = param2;
//truly groundbreaking algorithm here
return _param1 + " - " + _param2;
}
}
}
I am wondering two things:
1) I have thought that I need to be working with local "copies" of my parameters inside the "locked code"; because if another thread calls my method with different values for param1 and param2, that could mess up my processing. If I only work with variables that are declared/instantiated inside the locked code (i.e. _param1 and _param2 in the example above), then something could change the values of param1 and param2 (or send in references to different objects) and I am okay. But do I need to do that? Am I being unnecessarily paranoid?
2) I have decided that I don't want to instantiate my lock objects until I need them, because my collection of static locking objects is growing... So, I am now moving to doing this:
private static Object staticLock1;
public static string StaticMethod1(string param1, int param2) {
lock(staticLock1 = staticLock1 ?? new Object()) {
(...)
}
}
Is there any reason that instantiating my lock object the first time I need it is unsafe? Will using the assignment operator on my lock object in my lock statement somehow cause me problems or prevent the object from being properly locked?
What you have there won't make any difference at all - the arguments themselves cannot change after the call has been made, so it really does nothing. In your case with strings, it's perfectly safe seeing how string is immutable. When that isn't the case, it is possible that whatever is passed is altered somewhere else. In that case you'd have to make a real copy (i.e. not just copying the reference),
Consider the case where two threads arrive at lock(staticLock1 = staticLock1 ?? new Object()) at the same time. They could both see staticLock1 as null. So no that's not safe!
Your main confusion seems to be around what synchronization you need in order to safely call a static method concurrently.
Data races always arise because multiple threads access the same storage location in an unsynchronized way, and at least one of them is a writer. This basic rule is enough to reason about a lot of concurrency issues.
When you call a method, the arguments have different storage locations for each call. They are independent. Therefore, two threads calling the same method never race to access method arguments. You therefore never need to synchronize access to method arguments.
The same goes for locals. In fact, arguments have identical synchronization properties as locals have. They exist per call.
To answer your second issue: That is unsafe because two threads might lock on different objects. Also, you write to staticLock1 unsynchronized on multiple threads. I already explained that this is a data-race.
First: the overhead of creating an instance of Object is extremely small. Don't worry about it unless measurements show you that you should.
Just initialize like this:
private readonly static object staticLock1 = new Object();
The way you use the lock statement is not safe.
Secondly: I see no shared data in the methods so there is no reason to lock.
Finally: I would reconsider the design if it contains many static functions.

Is there any ThreadStatic attribute for parent and child threads

Is there any attribute or some method of sharing a value between a thread and the background workers it creates?
I am making a SQL Server CLR assembly that does a search in the database + some calculations, and I want it to be multi threading. I need to share some data between the calling thread and the background workers I create (what is read from the calling thread from database, I want to be passed to the workers, so that they compute what I need).
I don't think that sending a class object as parameter to the RunWorkerAsync is a good idea, since inside the threads I use lock(item); and Interlocked.Add(ref itemCount, -1); mechanism.
What I also need, is that if another search call is made, the values from these 2 call stacks are not mixed up.
Thank you!
Instead of using ThreadStatic variables like you want, you might consider passing your integer as a parameter, but instead of passing it raw, wrap it in a holder object.
class ResultHolder
{
public int result;
}
You can then use the object to hold your int by reference.
Thread t = new Thread(Run);
var holder = new ResultHolder() { result = 0x92 }
t.Start(holder);
// Query the result
Console.WriteLine(holder.result);

Execute static method in multithreads

Suppose I have a class like below:
public static class Foo
{
public static int Do(int original)
{
int result=original + 1;
return result;
}
}
public class Bar
{
public void Invoke()
{
int result=Foo.Do(1);
}
}
Anyone can tell me how it be invoked in CLR? All we know that CLR is a virtual machine base on stack. An instance which would invoke Foo.Do() method has its own Call Stack. It push a int arg to Stack , and then call Foo.Do() method. I'm woudering whether few instances in multithreads invoke Foo.Do() would disturb each others? Every instance has a copy of Foo.Do() or rather?
Each thread has its own call stack set up. So when you call a function in one thread, the stack is changed only for that thread. Other threads can call whatever other functions they want, without affecting each other (aside from shared state, but that's another issue. The important thing is that the stack isn't shared).
I'm woudering whether few instances in multithreads invoke Foo.Do() would disturb each others? Every instance has a copy of Foo.Do() or rather?
In this case, each instance would be fine. There is no data shared between the separate threads, since Invoke and Foo.Do do not rely on any other shared state.
The main issues with multiple threads occur when you're trying to share data between the individual threads. At that point, you need to take care to synchronize the access to the shared data.
Perphas you should look at ThreadLocal API so you can have a thread specific storage. In your case as Reed suggested, it should not matter as there is no shared state but if there is any, it will matter as static storage is shared between threads until unless it is ThreadLocal

Categories