I am trying to accomplish the following functionality,
I get a HttpRequest and based on the request, i will create a new thread and then set some data for this thread [ local and thread specific data ] and then i will spin the thread. In the thread, i must be able to consume that data that i initialized before creating this thread anywhere before this thread ends its life.
I tried this sample and here, the greeting variable inside the thread was null. Any idea of how do i accomplish this process.
class Program
{
[ThreadStatic]
static string greeting = "Greetings from the current thread";
static void Main()
{
Console.WriteLine(greeting); // prints initial value
greeting = "Goodbye from the main thread";
Thread t = new Thread(ThreadMethod);
t.Start();
t.Join();
Console.WriteLine(greeting); // prints the main thread's copy
Console.ReadKey();
}
static void ThreadMethod()
{
// I am getting greeting as null inside this thread method.
Console.WriteLine(greeting); // prints nothing as greeting initialized on main thread
greeting = "Hello from the second thread"; // only affects the second thread's copy
Console.WriteLine(greeting);
}
}
EDIT
I am trying to accomplish something like this
class ThreadTest
{
static void Main()
{
var tcp = new ThreadContextData();
Thread t = new Thread(ThreadMethod);
tcp.SetThreadContext("hi.. from t1");
t.Start();
t.Join();
Thread t2 = new Thread(ThreadMethod);
tcp.SetThreadContext("hello.. from t2");
t2.Start();
t2.Join();
Console.ReadKey();
}
static void ThreadMethod()
{
Console.WriteLine(new ThreadContextData().GetThreadContextValue());
}
}
public class ThreadContextData
{
static ThreadLocal<string> greeting;
static ThreadContextData()
{
greeting = new ThreadLocal<string>(() => "");
}
public void SetThreadContext(string contextValue)
{
greeting.Value = contextValue;
}
public string GetThreadContextValue()
{
return greeting.Value;
}
public void ClearThreadContextValue()
{
greeting.Value = null;
}
}
The Thread class has a method Start(object) which you can use to provide parameters to the thread, provided that your thread-routine also takes a parameter:
var thr = new Thread(foo);
thr.Start(7);
private void foo(object arg)
{
int data = (int)arg; // == 7
}
However, if you have access to relatively recent .Net platform, you can use inline lambdas to get that less verbose:
var thr = new Thread(_ => foo(7, "Marie", 123.44));
thr.Start();
private void foo(int data, string name, double age)
{
// ...
}
You are setting variable in one thread and trying to read in a new thread. I think you should use something like:
Thread thread = new Thread(Start);
thread.Start("greetings from ...");
private static void Start(object o)
{
var greeting = o as string;
Console.WriteLine(greeting);
}
ThreadStatic means that each thread gets it's own version of the variable. As such, in your current code, saying greeting = "Goodbye from the main thread"; sets the main thread's version of this variable, not the thread you're running.
You can only set thread static variables from within the thread.
I would instead package all the state needed to pass to the subthread together in a class, and then pass a reference to that class as data in the thread startup function.
Also, be aware that starting threads in ASP.NET code is generally a bad idea.
Related
A ThreadPool is created that does all the work on one thread and notifies when the work is done. The thread is started and the methods Execute1 and Execute2 are not displayed, but Done1 and Done2 are not displayed, although in the debugger execution reaches handle.Finished.
public class MyThreadPool
{
private readonly Thread[] _Threads;
public delegate void ParameterizedThreadStart(object? obj);
public MyThreadPool()
{
_Threads = new Thread[1];
}
public HandleEvent QueueUserWorkItem(System.Threading.ParameterizedThreadStart callBack)
{
var thread = new Thread(callBack) { IsBackground = true };
_Threads[0] = thread;
_Threads[0].Start();
return new HandleEvent();
}
}
public class HandleEvent : EventArgs
{
public event EventHandler? Finished;
protected virtual void onFinished(object e, EventArgs s)
{
Finished?.Invoke(this, EventArgs.Empty);
}
public HandleEvent ()
{
onFinished("sddd", EventArgs.Empty);
}
}
public static class Program
{
public static void Main()
{
static void ExecuteMethod2(object execute)
{
Console.WriteLine("Hello from the thread pool.");
}
static void ExecuteMethod1(object execute)
{
Console.WriteLine("Hello from the thread pool.");
}
var thread_pool = new MyThreadPool();
var handle1 = thread_pool.QueueUserWorkItem(ExecuteMethod1);
handle1.Finished += (o, a) => { Console.WriteLine($"Done 1"); };
var handle2 = thread_pool.QueueUserWorkItem(ExecuteMethod2);
handle2.Finished += (o, a) => { Console.WriteLine($"Done 2"); };
}
}
The problem is that the onFinished method is never called. This should be called once the thread has completed execution of its callback, but it is not. For this to work the QueueUserWorkItem needs to wrap the callback in a method that does this, i.e. something like
var result = new HandleEvent();
void localExecute(object execute)
{
callBack(execute); // run the actual work
result.onFinished(); // Raise the finished method
}
var thread = new Thread(localExecute) { IsBackground = true };
_Threads[0] = thread;
_Threads[0].Start();
return result ;
However, there are other issues:
There is no actual thread pooling going on. The point of a threadpool is that threads are expensive to create, so you keep them around in a pool instead of creating new ones. The threads should be in a blocked state while in the pool, so the pool can assign the thread a task and wake it when needed.
There is no synchronization going on, so the program may very well complete before all threads are done. So you may want to return something like a ManualResetEvent that can be waited on, instead of your own custom event.
There is rarely any reason to implement your own thread pool, and doing so well is quite difficult. So I really hope you are doing this for educational purposes, and do not intend to use the result in real life.
Somewhere on my main thread i make a new thread which creates an object that is only allowed to be instantiated once through the entire application time.
Further down my main thread i have a function that makes use of this object that is also a global variable by the way.
So i wish to run this function on the same thread that the object was created.
Question is how can i achieve this when it is the Main threads decision when this function should be called?
// global variable
private static IWebDriver driver;
// Main Thread thread creation
Thread thread = new Thread(() =>
{
driver = new ChromeDriver(#"myPath");
});
thread.Start();
// some click event on main thread
myFunctionUsingDriverObject();
So i need some way to tell the function to run on the same thread as driver was created. Usually you would use the methodInvoker but the IWebDriver does not have such a method. So is there another way i can invoke the function into the thread of driver?
If anyone is wondering why i want to do this. Then it is because the UI is run on the Main Thread and then the function will freeze the UI until completion if it is also run on the main thread.
Add a reference to the WindowsBase.dll and write this code:
private static IWebDriver driver;
private static Dispatcher dispatcher = null;
AutoResetEvent waitHandle = new AutoResetEvent(false);
var thread = new Thread(() =>
{
dispatcher = Dispatcher.CurrentDispatcher;
waitHandle.Set();
Dispatcher.Run();
});
thread.Start();
waitHandle.WaitOne();
// Now you can use dispatcher.Invoke anywhere you want
dispatcher.Invoke(() =>
{
driver = new ChromeDriver(#"myPath");
});
// And async for not blocking the UI thread
dispatcher.BeginInvoke(new Action(() =>
{
myFunctionUsingDriverObject();
}));
// or using await
await dispatcher.InvokeAsync(() =>
{
});
// And when you are done, you can shut the thread down
dispatcher.InvokeShutdown();
You could use a singleton class or if you wanted to ensure that this could only run once for all applications, a service class that is based on a Mutex. I will show you the former as this seems more applicable as far as I can make out
public interface IDriverService
{
void StartDriverService();
void StopDriverService();
void PerformDriverAction();
}
Now an implementation
public class ChromeDriverService : IDriverService
{
private static ChromeDriverService instance;
private readonly Thread _thread;
private readonly ConcurrentQueue<Action> _actions = new ConcurrentQueue<Action>();
private volatile bool _running;
private ChromeDriverService()
{
_thread = new Thread();
_thread.Start();
}
public static IDriverService Instance()
{
if (instance == null)
instance = new ChromeDriverService();
return instance;
}
// This will run on the "target" _thread
public void StartDriverService()
{
while (true)
{
Action action;
if (_actions.TryDequeue(out action))
{
try
{
action();
}
catch (Exception ex) { // Handle }
}
else
{
if (!_running && _actions.IsEmpty)
return;
}
}
}
public void StopDriverService()
{
_running = false;
// IMPORTANT: Finish the logic here - we have a chance for race conditions. Dequeuing before the
// last action runs for example. This is primative, but you will have to take care of this.
while (!_actions.IsEmpty)
{
// Do stuff.
}
}
// Called from some other thread.
public void PerformDriverAction(Action action)
{
if (_running)
_actions.Enqueue(action);
}
}
This is a primitive example and I have not attempted to run or compile this (I am on my phone).
Note, I am not doing anything with the actual ChromeDriver. This class can be simply edited to work with such an object.
I hope this helps.
I'm writing an application that uses a separate thread for logging.
I'd like to stop the separate thread when the main thread stops. However I'm unable to figure out when to stop the logger thread exactly as I don't know when the main thread stops. Is there a mechanism in C# that would send a notification when the main thread stops? (Or can you think about another solution to my problem?)
// This class automatically applies on each call of every method of Main() function
public class CommandLoggingAdvice : IMethodInterceptor
{
private static ProducerConsumerClass LoggingQueue = ProducerConsumerClass.Instance;
LoggingQueue.AddTask("Logging message on call of *method*");
}
public sealed class ProducerConsumerClass
{
// here Iget an instance of log4net
private ILog _Logger = null;
protected ILog Logger
{
_Logger = LogManager.GetLogger("Logger1");
}
private BlockingCollection<string> tasks = new BlockingCollection<string>();
private static volatile ProducerConsumerClass _instance;
Thread worker;
private Thread mainthread;
private ProducerConsumerClass()
{
mainthread = Thread.CurrentThread;
worker = new Thread(Work);
worker.Name = "Queue thread";
worker.IsBackground = false;
worker.Start(mainthread);
}
public static ProducerConsumerClass Instance
{
get
{
if (_instance == null)
{
_instance = new ProducerConsumerClass();
}
}
}
public void AddTask(string task)
{
tasks.Add(task);
}
void Work(object mainthread)
{
Thread ma = (Thread) mainthread;
if(ma.ThreadState != ThreadState.Stopped)
{
tasks.CompleteAdding();
}
while (true)
{
string task = null;
if (!tasks.IsCompleted)
{
task = tasks.Take();
Logger1.Info(task);
}
else
{
return;
}
}
}
}
If BlockingCollection is empty and application is still working, loop calls one more Take() and result: logger thread is paused now. So when main thread.Threadstate == Stopped, i need to kill logger thread
More info about issue were added in comments
You already have code in the thread that exits if the BlockingCollection is empty and marked as completed. Your loop checks for IsCompleted and exits.
What you need is some way for the main thread to call CompleteAdding on the collection. I would recommend a public method in your ProducerConsumerClass:
public void AllDone()
{
tasks.CompleteAdding();
}
So the main thread can call AllDone when it's done processing. Your thread will then empty the queue and exit.
By the way, a more concise way to write your logging loop is:
foreach (string task in tasks.GetConsumingEnumerable())
{
Logger1.Info(task);
}
This also makes it easier to add cancellation support in the future.
I have an method Process(Progressbar) in class Blacklist
i tried to use this :
Thread thread = new Thread(() => Blacklist.Process(pgImportProcess));
it occurs an error
C# 3.0 language Feature
So how can i create a thread and parse progressbar as a parameter?
Thank in advance
have you tried:
void Invoker(){
ParameterizedThreadStart pts = Start;
Thread thread = new Thread(pts);
thread.Start(new object());
}
public void Start(object o)
{
//do stuff
}
You can't access a UI object from a different thread than it was created on. Every Control has an Invoke method that will execute a delegate on the UI thread. For example if you need to update your progress bars progress:
progressBar.Invoke(new Action() { () => progressBar.Value = updateValue; });
So you just need to use the Thread constructor that takes a ParameterizedThreadStart delegate.
Thread thread = new Thread(StartProcess);
thread.Start(pgImportProcess);
...
private static void StartProcess(object progressBar) {
Blacklist.Process((ProgressBar)progressBar);
}
Can you create a class to passing your parameter like
public class Sample
{
object _value;
public Sample(object value)
{
this._value = value;
}
public void Do()
{
// dosomething
// Invoke the Process(value)
}
}
And then
Sample p = new Sample("your parameter : Progressbar");
new Thread(new ThreadStart(p.Do)).Start();
WinForm:
I have a method called check_news in my MainApplication.
How can I create and run a Thread that will work on the method on background each time I call the method (by pushing a button, or in the start of the program)?
I know how to create a thread but how can I create new thread every time I call the function (new thread because the old one is dead)?
Should I create a new class and run the thread with the new class object and the method I need?
Where should I define the thread?
public void Example()
{
//call using a thread.
ThreadPool.QueueUserWorkItem(p => check_news("title", "news message"));
}
private void check_news(string news, string newsMessage)
{
}
You can just create a thread inside the method by writing new Thread(...).
The ... can be a method name, delegate instance, or anonymous method.
Each time this code executes, it will create a new Thread instance.
Note that it will be more efficient to use the ThreadPool instead.
I suppose the best way to achieve this is by adding it to the thread pool, it's easy and quick.
Example:
public static void Main(string[] args)
{
check_news();
}
private static void check_news()
{
ThreadPool.QueueUserWorkItem((obj) =>
{
// Fetch the news here
Thread.Sleep(1000); // Dummy
});
}
Or if you really want to deal with it yourself, this is something you could use:
public static void Main(string[] args)
{
check_news();
Console.ReadKey();
}
private static void check_news()
{
Thread t = new Thread(() =>
{
// Check news here
Thread.Sleep(1000); // Dummy
});
t.Priority = ThreadPriority.Lowest; // Priority of the thread
t.IsBackground = true; // Set it as background (allows you to stop the application while news is fetching
t.Name = "News checker"; // Make it recognizable
t.Start(); // And start it
}
But you should know that this takes a longer time to start, it doesn't reuse threads, and there's not a real advantage in it.
Or if you want more control you could use the async platform:
public static void Main(string[] args)
{
check_news(); // You can add an argument 'false' to stop it from executing async
Console.WriteLine("Done");
Console.ReadKey();
}
public delegate void Func();
public static void check_news(bool async = true)
{
Func checkNewsFunction = () =>
{
//Check news here
Thread.Sleep(1000);
};
if (async)
{
AsyncCallback callbackFunction = ar =>
{
// Executed when the news is received
};
checkNewsFunction.BeginInvoke(callbackFunction, null);
}
else
checkNewsFunction();
}
Note that the lambda expressions in all examples can just as well be replaced by regular functions. But I just use them right now, because it seems nicer as example.