I have a "string" and a "StreamReader" in the main thread. I want to pass these to a thread which will read the streamreader into the string. I want that string to be changed in the main thread. My question is how do I do this?
Additional info: I have specific reasons as to why I want to thread this so please just stick to the specs. Also, I cannot use TPL because I cannot get framework 4.0... Again for specific reasons.
So you make a class with a string and a StreamReader property. You pass in an instance of that class to your other thread using ParameterizedThreadStart. You have that other thread fill that buttercup up by writing to the string property on that instance of your class.
When the thread is done, your string property on the instance of your class will be filled up. Yay.
So something like
class Foo {
public string Bar { get; set; }
}
Then:
Foo foo = new Foo();
var thread = new Thread(o => { Foo f = (Foo)o; f.Bar = "FillMeUpButterCup"; });
thread.Start(foo);
thread.Join();
Console.WriteLine(foo);
Wow!
I left off the StreamReader but now you get the point.
When creating the thread you have ParameterizedThreadStart delegate and a parameter that you could pass there. Just create a class with two properties - string and StreamReader (and possibly whatever else you want to pass there) and pass instance of the class into thread starting method.
public class ThreadStartParam
{
public string Str { get; set; }
public StreamReader StreamReader { get; set; }
}
class Program
{
static void Main(string[] args)
{
var t = new Thread(YourMethod);
var param = new ThreadStartParam();
param.Str = "abc";
param.StreamReader = new StreamReader();
t.Start(param);
}
static void YourMethod(object param)
{
var p = (ThreadStartParam) param;
// whatever
}
}
I wrote a blog post about this sometime last year and I think it'll cover how to properly communicate to a thread and back from a thread. Basically create an object to pass to and from the thread and you can pass to the thread using a ParameterizedThreadStart and you can pass back by having a delegate to invoke.
http://coreyogburn.com/post/Threads-Doing-Them-Right-wGUI.aspx
More specifically in your example of the main thread realizing the changed String that you pass to the thread, I would recommend that on thread completion, you call a method that passes the string value back and re-sets the original string's value. This will prevent the thread from adding to the string while the main thread might try to read it.
Related
In C# threads are created by passing a member function:
class SomeClass {
public void ThreadFunction() {Thread.Sleep( Infinite ); }
};
SomeClass myObject = new SomeClass();
Thread thread = new Thread( myObject.ThreadFunction );
thread.Start();
Here ThreadFunction() is not static, so I guess the object reference is passed to Thread constructor.
How can code inside ThreadFunction() get to myObject? Do I just use this reference for that?
Like this:
class SomeClass {
public void ThreadFunction(Object obj)
{
SomeClass myObject = (SomeClass)obj;
Thread.Sleep( Infinite );
}
};
SomeClass myObject = new SomeClass();
Thread thread = new Thread(new ParameterizedThreadStart(myObject.ThreadFunction) );
thread.Start(myObject)
In the exact example you give, simply by accessing this.
In the general case, you can also do something like
class SomeClass {
public void ThreadFunction(object param)
{
var justAnExample = (string)param;
}
};
SomeClass myObject = new SomeClass();
Thread thread = new Thread(myObject.ThreadFunction);
thread.Start("parameter");
This allows you to pass a parameter of any type (here, a string) to the thread function. If you need more than one, then you can always pass in a Tuple or an object[] or any other container of values.
If you go this way, you might want to make ThreadFunction static (this will lose you the option of using this) as well.
I Working on desktop application where i am get struck.
I have a method through I am doing HTTP Post And Get. I am managing this object through ref in entire application.
This object fetching category from website and i am using same ref for posting as well.
This category Fetcher method return datatable of categories. This Method hang my UI, So i need to implement this in thread.
But i don't know how to pass ref in thread and get return values.
This is How I am passing values.
Categorydt = objPostDataFetcher.FetchCategories(ref httpHelper);
I want to call this method in Thread. Please give me any idea and suggestion.
Thanks in Advance.
I think this should solve the problem of passing ref.
new Thread(() => { YourMethod(ref httpHelper);
in your case, it looks to be
new Thread(() => { objPostDataFetcher.FetchCategories(ref httpHelper);
And if you want to use method with return type in thread, you can use this link
how to call the method in thread with aruguments and return some value
Good Luck :)
The simplest approach would be to use an asynchronous delegate, as this will give you parameter passing and return values. However, it is worth bearing in mind that this will run on a thread-pool thread and may not be suitable if your calls are very long-running. Anyway, start with delegates and see how it performs. There is a good tutorial here:
http://msdn.microsoft.com/en-us/library/h80ttd5f.aspx
If don't want your method to hang user interface you should use BackgroundWorker class. Look at http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx.
Best regards.
Here's how to invoke a worker method on its own thread that invokes a callback to pass data back to the main thread:
class Program
{
public static volatile bool done = false;
static void Main(string[] args)
{
WorkerClass worker = new WorkerClass();
worker.Callback = new WorkerCallbackDelegate(WorkerCallback);
System.Threading.Thread thread = new System.Threading.Thread(worker.DoWork);
thread.Start();
while (!done)
{
System.Threading.Thread.Sleep(100);
}
Console.WriteLine("Done");
Console.ReadLine();
}
public static void WorkerCallback(object dataArg)
{
// handle dataArg
done = true;
}
}
public delegate void WorkerCallbackDelegate(object dataArg);
class WorkerClass
{
public WorkerCallbackDelegate Callback { get; set; }
public void DoWork()
{
// do your work and load up an object with your data
object data = new object();
Callback(data);
}
}
How to pass parameters to Thread.ThreadStart() method in C#?
Suppose I have method called 'download'
public void download(string filename)
{
// download code
}
Now I have created one thread in the main method:
Thread thread = new Thread(new ThreadStart(download(filename));
error method type expected.
How can I pass parameters to ThreadStart with target method with parameters?
The simplest is just
string filename = ...
Thread thread = new Thread(() => download(filename));
thread.Start();
The advantage(s) of this (over ParameterizedThreadStart) is that you can pass multiple parameters, and you get compile-time checking without needing to cast from object all the time.
Look at this example:
public void RunWorker()
{
Thread newThread = new Thread(WorkerMethod);
newThread.Start(new Parameter());
}
public void WorkerMethod(object parameterObj)
{
var parameter = (Parameter)parameterObj;
// do your job!
}
You are first creating a thread by passing delegate to worker method and then starts it with a Thread.Start method which takes your object as parameter.
So in your case you should use it like this:
Thread thread = new Thread(download);
thread.Start(filename);
But your 'download' method still needs to take object, not string as a parameter. You can cast it to string in your method body.
You want to use the ParameterizedThreadStart delegate for thread methods that take parameters. (Or none at all actually, and let the Thread constructor infer.)
Example usage:
var thread = new Thread(new ParameterizedThreadStart(download));
//var thread = new Thread(download); // equivalent
thread.Start(filename)
You could also delegate like so...
ThreadStart ts = delegate
{
bool moreWork = DoWork("param1", "param2", "param3");
if (moreWork)
{
DoMoreWork("param1", "param2");
}
};
new Thread(ts).Start();
In Additional
Thread thread = new Thread(delegate() { download(i); });
thread.Start();
I would recommend you to have another class called File.
public class File
{
private string filename;
public File(string filename)
{
this.filename= filename;
}
public void download()
{
// download code using filename
}
}
And in your thread creation code, you instantiate a new file:
string filename = "my_file_name";
myFile = new File(filename);
ThreadStart threadDelegate = new ThreadStart(myFile.download);
Thread newThread = new Thread(threadDelegate);
You can encapsulate the thread function(download) and the needed parameter(s)(filename) in a class and use the ThreadStart delegate to execute the thread function.
public class Download
{
string _filename;
Download(string filename)
{
_filename = filename;
}
public void download(string filename)
{
//download code
}
}
Download = new Download(filename);
Thread thread = new Thread(new ThreadStart(Download.download);
How about this: (or is it ok to use like this?)
var test = "Hello";
new Thread(new ThreadStart(() =>
{
try
{
//Staff to do
Console.WriteLine(test);
}
catch (Exception ex)
{
throw;
}
})).Start();
According to your question...
How to pass parameters to Thread.ThreadStart() method in C#?
...and the error you encountered, you would have to correct your code from
Thread thread = new Thread(new ThreadStart(download(filename));
to
Thread thread = new Thread(new ThreadStart(download));
thread.Start(filename);
However, the question is more complex as it seems at first.
The Thread class currently (4.7.2) provides several constructors and a Start method with overloads.
These relevant constructors for this question are:
public Thread(ThreadStart start);
and
public Thread(ParameterizedThreadStart start);
which either take a ThreadStart delegate or a ParameterizedThreadStart delegate.
The corresponding delegates look like this:
public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);
So as can be seen, the correct constructor to use seems to be the one taking a ParameterizedThreadStart delegate so that some method conform to the specified signature of the delegate can be started by the thread.
A simple example for instanciating the Thread class would be
Thread thread = new Thread(new ParameterizedThreadStart(Work));
or just
Thread thread = new Thread(Work);
The signature of the corresponding method (called Work in this example) looks like this:
private void Work(object data)
{
...
}
What is left is to start the thread. This is done by using either
public void Start();
or
public void Start(object parameter);
While Start() would start the thread and pass null as data to the method, Start(...) can be used to pass anything into the Work method of the thread.
There is however one big problem with this approach:
Everything passed into the Work method is cast into an object. That means within the Work method it has to be cast to the original type again like in the following example:
public static void Main(string[] args)
{
Thread thread = new Thread(Work);
thread.Start("I've got some text");
Console.ReadLine();
}
private static void Work(object data)
{
string message = (string)data; // Wow, this is ugly
Console.WriteLine($"I, the thread write: {message}");
}
Casting is something you typically do not want to do.
What if someone passes something else which is not a string? As this seems not possible at first (because It is my method, I know what I do or The method is private, how should someone ever be able to pass anything to it?) you may possibly end up with exactly that case for various reasons. As some cases may not be a problem, others are. In such cases you will probably end up with an InvalidCastException which you probably will not notice because it simply terminates the thread.
As a solution you would expect to get a generic ParameterizedThreadStart delegate like ParameterizedThreadStart<T> where T would be the type of data you want to pass into the Work method. Unfortunately something like this does not exist (yet?).
There is however a suggested solution to this issue. It involves creating a class which contains both, the data to be passed to the thread as well as the method that represents the worker method like this:
public class ThreadWithState
{
private string message;
public ThreadWithState(string message)
{
this.message = message;
}
public void Work()
{
Console.WriteLine($"I, the thread write: {this.message}");
}
}
With this approach you would start the thread like this:
ThreadWithState tws = new ThreadWithState("I've got some text");
Thread thread = new Thread(tws.Work);
thread.Start();
So in this way you simply avoid casting around and have a typesafe way of providing data to a thread ;-)
here is the perfect way...
private void func_trd(String sender)
{
try
{
imgh.LoadImages_R_Randomiz(this, "01", groupBox, randomizerB.Value); // normal code
ThreadStart ts = delegate
{
ExecuteInForeground(sender);
};
Thread nt = new Thread(ts);
nt.IsBackground = true;
nt.Start();
}
catch (Exception)
{
}
}
private void ExecuteInForeground(string name)
{
//whatever ur function
MessageBox.Show(name);
}
I've found the "ThreadStatic" attribute to be extremely useful recently, but makes me now want a "ThreadLocal" type attribute that lets me have non-static data members on a per-thread basis.
Now I'm aware that this would have some non-trivial implications, but:
Does such a thing exist already built into C#/.net? or since it appears so far that the answer to this is no (for .net < 4.0), is there a commonly used implementation out there?
I can think of a reasonable way to implement it myself, but would just use something that already existed if it were available.
Straw Man example that would implement what I'm looking for if it doesn't already exist:
class Foo
{
[ThreadStatic]
static Dictionary<Object,int> threadLocalValues = new Dictionary<Object,int>();
int defaultValue = 0;
int ThreadLocalMember
{
get
{
int value = defaultValue;
if( ! threadLocalValues.TryGetValue(this, out value) )
{
threadLocalValues[this] = value;
}
return value;
}
set { threadLocalValues[this] = value; }
}
}
Please forgive any C# ignorance. I'm a C++ developer that has only recently been getting into the more interesting features of C# and .net
I'm limited to .net 3.0 and maybe 3.5 (project has/will soon move to 3.5).
Specific use-case is callback lists that are thread specific (using imaginary [ThreadLocal] attribute) a la:
class NonSingletonSharedThing
{
[ThreadLocal] List<Callback> callbacks;
public void ThreadLocalRegisterCallback( Callback somecallback )
{
callbacks.Add(somecallback);
}
public void ThreadLocalDoCallbacks();
{
foreach( var callback in callbacks )
callback.invoke();
}
}
Enter .NET 4.0!
If you're stuck in 3.5 (or earlier), there are some functions you should look at, like AllocateDataSlot which should do what you want.
You should think about this twice. You are essentially creating a memory leak. Every object created by the thread stays referenced and can't be garbage collected. Until the thread ends.
If you looking to store unique data on a per thread basis you could use Thread.SetData. Be sure to read up on the pros and cons http://msdn.microsoft.com/en-us/library/6sby1byh.aspx as this has performance implications.
Consider:
Rather than try to give each member variable in an object a thread-specific value, give each thread its own object instance. -- pass the object to the threadstart as state, or make the threadstart method a member of the object that the thread will "own", and create a new instance for each thread that you spawn.
Edit
(in response to Catskul's remark.
Here's an example of encapsulating the struct
public class TheStructWorkerClass
{
private StructData TheStruct;
public TheStructWorkerClass(StructData yourStruct)
{
this.TheStruct = yourStruct;
}
public void ExecuteAsync()
{
System.Threading.ThreadPool.QueueUserWorkItem(this.TheWorkerMethod);
}
private void TheWorkerMethod(object state)
{
// your processing logic here
// you can access your structure as this.TheStruct;
// only this thread has access to the struct (as long as you don't pass the struct
// to another worker class)
}
}
// now hte code that launches the async process does this:
var worker = new TheStructWorkerClass(yourStruct);
worker.ExecuteAsync();
Now here's option 2 (pass the struct as state)
{
// (from somewhere in your existing code
System.Threading.Threadpool.QueueUserWorkItem(this.TheWorker, myStruct);
}
private void TheWorker(object state)
{
StructData yourStruct = (StructData)state;
// now do stuff with your struct
// works fine as long as you never pass the same instance of your struct to 2 different threads.
}
I ended up implementing and testing a version of what I had originally suggested:
public class ThreadLocal<T>
{
[ThreadStatic] private static Dictionary<object, T> _lookupTable;
private Dictionary<object, T> LookupTable
{
get
{
if ( _lookupTable == null)
_lookupTable = new Dictionary<object, T>();
return _lookupTable;
}
}
private object key = new object(); //lazy hash key creation handles replacement
private T originalValue;
public ThreadLocal( T value )
{
originalValue = value;
}
~ThreadLocal()
{
LookupTable.Remove(key);
}
public void Set( T value)
{
LookupTable[key] = value;
}
public T Get()
{
T returnValue = default(T);
if (!LookupTable.TryGetValue(key, out returnValue))
Set(originalValue);
return returnValue;
}
}
Although I am still not sure about when your use case would make sense (see my comment on the question itself), I would like to contribute a working example that is in my opinion more readable than thread-local storage (whether static or instance). The example is using .NET 3.5:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Linq;
namespace SimulatedThreadLocal
{
public sealed class Notifier
{
public void Register(Func<string> callback)
{
var id = Thread.CurrentThread.ManagedThreadId;
lock (this._callbacks)
{
List<Func<string>> list;
if (!this._callbacks.TryGetValue(id, out list))
{
this._callbacks[id] = list = new List<Func<string>>();
}
list.Add(callback);
}
}
public void Execute()
{
var id = Thread.CurrentThread.ManagedThreadId;
IEnumerable<Func<string>> threadCallbacks;
string status;
lock (this._callbacks)
{
status = string.Format("Notifier has callbacks from {0} threads, total {1} callbacks{2}Executing on thread {3}",
this._callbacks.Count,
this._callbacks.SelectMany(d => d.Value).Count(),
Environment.NewLine,
Thread.CurrentThread.ManagedThreadId);
threadCallbacks = this._callbacks[id]; // we can use the original collection, as only this thread can add to it and we're not going to be adding right now
}
var b = new StringBuilder();
foreach (var callback in threadCallbacks)
{
b.AppendLine(callback());
}
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine(status);
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(b.ToString());
}
private readonly Dictionary<int, List<Func<string>>> _callbacks = new Dictionary<int, List<Func<string>>>();
}
public static class Program
{
public static void Main(string[] args)
{
try
{
var notifier = new Notifier();
var syncMainThread = new ManualResetEvent(false);
var syncWorkerThread = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(delegate // will create closure to see notifier and sync* events
{
notifier.Register(() => string.Format("Worker thread callback A (thread ID = {0})", Thread.CurrentThread.ManagedThreadId));
syncMainThread.Set();
syncWorkerThread.WaitOne(); // wait for main thread to execute notifications in its context
syncWorkerThread.Reset();
notifier.Execute();
notifier.Register(() => string.Format("Worker thread callback B (thread ID = {0})", Thread.CurrentThread.ManagedThreadId));
syncMainThread.Set();
syncWorkerThread.WaitOne(); // wait for main thread to execute notifications in its context
syncWorkerThread.Reset();
notifier.Execute();
syncMainThread.Set();
});
notifier.Register(() => string.Format("Main thread callback A (thread ID = {0})", Thread.CurrentThread.ManagedThreadId));
syncMainThread.WaitOne(); // wait for worker thread to add its notification
syncMainThread.Reset();
notifier.Execute();
syncWorkerThread.Set();
syncMainThread.WaitOne(); // wait for worker thread to execute notifications in its context
syncMainThread.Reset();
notifier.Register(() => string.Format("Main thread callback B (thread ID = {0})", Thread.CurrentThread.ManagedThreadId));
notifier.Execute();
syncWorkerThread.Set();
syncMainThread.WaitOne(); // wait for worker thread to execute notifications in its context
syncMainThread.Reset();
}
finally
{
Console.ResetColor();
}
}
}
}
When you compile and run the above program, you should get output like this:
alt text http://img695.imageshack.us/img695/991/threadlocal.png
Based on your use-case I assume this is what you're trying to achieve. The example first adds two callbacks from two different contexts, main and worker threads. Then the example runs notification first from main and then from worker threads. The callbacks that are executed are effectively filtered by current thread ID. Just to show things are working as expected, the example adds two more callbacks (for a total of 4) and again runs the notification from the context of main and worker threads.
Note that Notifier class is a regular instance that can have state, multiple instances, etc (again, as per your question's use-case). No static or thread-static or thread-local is used by the example.
I would appreciate if you could look at the code and let me know if I misunderstood what you're trying to achieve or if a technique like this would meet your needs.
I'm not sure how you're spawning your threads in the first place, but there are ways to give each thread its own thread-local storage, without using hackish workarounds like the code you posted in your question.
public void SpawnSomeThreads(int threads)
{
for (int i = 0; i < threads; i++)
{
Thread t = new Thread(WorkerThread);
WorkerThreadContext context = new WorkerThreadContext
{
// whatever data the thread needs passed into it
};
t.Start(context);
}
}
private class WorkerThreadContext
{
public string Data { get; set; }
public int OtherData { get; set; }
}
private void WorkerThread(object parameter)
{
WorkerThreadContext context = (WorkerThreadContext) parameter;
// do work here
}
This obviously ignores waiting on the threads to finish their work, making sure accesses to any shared state is thread-safe across all the worker threads, but you get the idea.
Whilst the posted solution looks elegant, it leaks objects. The finalizer - LookupTable.Remove(key) - is run only in the context of the GC thread so is likely only creating more garbage in creating another lookup table.
You need to remove object from the lookup table of every thread that has accessed the ThreadLocal. The only elegant way I can think of solving this is via a weak keyed dictionary - a data structure which is strangely lacking from c#.
When an object is altered in a method that runs on a separate thread, the object is not altered on the calling thread (the thread that started the thread on which the method runs).
However, if the class that defines the object is generic, the object gets altered on the calling thread. For example:
I have two classes:
public class Holder<T> { public T Value {get;set;} }
And
public class Holder2 { public String Value {get;set;} }
I have a third object called client which on method Change() sets the Value to something different on a separate thread:
static void main(string[] args)
{
Holder<String> test = new Holder<String>();
test.Set("original");
Client client = new client(test);
client.Change(test);
Console.WriteLine(test.Value);
// test.Value now returns "changed"
// But if test was of type Holder2, it would return "original"
}
So basically what client does is:
public class Client
{
Holder<String> test;
public Client(Holder<String> test)
{
this.test = test;
}
public void Change()
{
ThreadStart ts = new ThreadStart(Alter);
Thread t = new Thread(ts);
t.Start();
}
public void Alter()
{
test.Value = "changed";
}
}
However, If I change the Client class to instead take Holder2, which isn't generic it does no longer work. That is to say, test.Value would return "original". Can anyone please explain to me, why is that?
Since you do not use locking there is a race-condition which might explain your observations.
Also: Please show how you display the variable after calling the client.Change(test);