i know i can get the Thread Name by calling Thread.CurrentThread.Name
but i got a tricky scenario.
i created two thread, each launch a new object (says objA) and run a method.
inside the object (objA) method (objAM), i create another object (says objB) and run a method (objBM).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TESTA a = new TESTA();
}
}
class TESTA
{
private Thread t;
public TESTA()
{
t = new Thread(StartThread);
t.Name = "ABC";
t.IsBackground = true;
t.Start();
t = new Thread(StartThread);
t.Name = "XYZ";
t.IsBackground = true;
t.Start();
}
private void StartThread()
{
objA thisA = new objA();
}
}
class objA
{
private System.Threading.Timer t1;
public objA()
{
objAM();
t1 = new Timer(new TimerCallback(testthread), null, 0, 1000);
}
private void objAM()
{
Console.WriteLine("ObjA:" + Thread.CurrentThread.Name);
}
private void testthread(object obj)
{
objB thisB = new objB();
}
}
class objB
{
public objB()
{
objBM();
}
private void objBM()
{
Console.WriteLine("ObjB:" + Thread.CurrentThread.Name);
}
}
}
but the value of Thread.CurrentThread.Name in objB return empty.
How can i get the Thread Name inside objBM?
From description of System.Threading.Timer: The method does not execute on the thread that created the timer; it executes on a ThreadPool thread supplied by the system.
Thus your testthread method executed on unnamed ThreadPool thread. Btw you can verify it by calling Thread.CurrentThread.IsThreadPoolThread.
Related
I'm messing around with multithreading and making some sort of task engine. The idea is that the engine can have a configurable amount of threads waiting and when a new task arrives the first free thread picks it up and executes it.
The problem is that something 2 threads pickup the same task somehow. I looked it through and I think that this code should work but obviously it doesn't. If I add the 10ms sleep where it is now commented out it works, but I'm not sure I understand why. It looks like the .Reset() function returns before it actually resets the event?
Can somebody explain? Is there a better way to let only a single thread continue when there are multiple waiting?
Thanks
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TaskTest
{
public class Engine
{
private ManualResetEvent taskEvent;
private ConcurrentQueue<Task> tasks;
private bool running;
private List<Thread> threads;
private int threadAmount;
private int threadsBusy = 0;
public Engine(int amountOfThreads)
{
taskEvent = new ManualResetEvent(false);
tasks = new ConcurrentQueue<Task>();
threads = new List<Thread>();
threadAmount = amountOfThreads;
}
public void Start()
{
running = true;
for (var i = 0; i < threadAmount; i++)
{
var thread = new Thread(Process);
thread.Name = "Thread " + i;
threads.Add(thread);
thread.Start();
}
}
public void Stop()
{
running = false;
taskEvent.Set();
threads.ForEach(t => t.Join());
}
private void Process()
{
while (running)
{
lock (taskEvent)
{
// Lock it so only a single thread is waiting on the event at the same time
taskEvent.WaitOne();
taskEvent.Reset();
//Thread.Sleep(10);
}
if (!running)
{
taskEvent.Set();
return;
}
threadsBusy += 1;
if (threadsBusy > 1)
Console.WriteLine("Failed");
Task task;
if (tasks.TryDequeue(out task))
task.Execute();
threadsBusy -= 1;
}
}
public void Enqueue(Task t)
{
tasks.Enqueue(t);
taskEvent.Set();
}
}
}
EDIT
Rest of the code:
namespace TaskTest
{
public class Start
{
public static void Main(params string[] args)
{
var engine = new Engine(4);
engine.Start();
while (true)
{
Console.Read();
engine.Enqueue(new Task());
}
}
}
}
namespace TaskTest
{
public class Task
{
public void Execute()
{
Console.WriteLine(Thread.CurrentThread.Name);
}
}
}
When using Console.Read() on a key press, two characters are read from the input. You should use Console.ReadLine() instead.
Note that your code can be simplified a lot by using a BlockingCollection to handle the synchronization:
public class Engine
{
private BlockingCollection<Task> tasks;
private List<Thread> threads;
private int threadAmount;
public Engine(int amountOfThreads)
{
tasks = new BlockingCollection<Task>();
threads = new List<Thread>();
threadAmount = amountOfThreads;
}
public void Start()
{
for (var i = 0; i < threadAmount; i++)
{
var thread = new Thread(Process);
thread.Name = "Thread " + i;
threads.Add(thread);
thread.Start();
}
}
public void Stop()
{
tasks.CompleteAdding();
threads.ForEach(t => t.Join());
}
private void Process()
{
foreach (var task in tasks.GetConsumingEnumerable())
{
task.Execute();
}
}
public void Enqueue(Task t)
{
tasks.Add(t);
}
}
I am having a lot of trouble with this. Consider this example:
public class Test {
Thread t;
public Test() {
t = new Thread(ThreadFunction);
}
public void Start() {
t.Start();
}
private void ThreadFunction() {
Thread.Sleep(5000);
Console.WriteLine("Function Complete");
}
}
public static class Main {
public Main() {
Test test = new Test();
test.Start();
// sleep longer than my worker so it finishes
Thread.Sleep(10000);
// a place to place a breakpoint
bool breakPointHere = true;
}
}
Now, I see the output of the console.log, but when I inspect Test's thread object, I see that IsAlive is still true, and ThreadStatus = TheadStatus.Running. Why is this? I wish to detect that the thread is truly complete, but I am confused as to how it can still be considered running if ThreadFunction() completes?
EDIT 2:
I finally tracked down the cause, Updating the code, and am going to answer my own question
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1 {
public abstract class Worker {
protected bool shutdown;
protected Thread t;
private bool _isStopped = true;
public bool IsStopped {
get {
return t.ThreadState == ThreadState.Stopped;
}
}
private bool _isPaused = false;
public bool IsPaused {
get {
return _isPaused;
}
}
private string stringRepresentation;
public Worker() {
t = new Thread(ThreadFunction);
stringRepresentation = "Thread id:" + t.ManagedThreadId;
t.Name = stringRepresentation;
}
public void Start() {
OnBeforeThreadStart();
t.Start();
}
public void ScheduleStop() {
shutdown = true;
}
public void SchedulePause() {
OnPauseRequest();
_isPaused = true;
}
public void Unpause() {
_isPaused = false;
}
public void ForceStop() {
t.Abort();
}
/// <summary>
/// The main thread loop.
/// </summary>
private void ThreadFunction() {
OnThreadStart();
while (!shutdown) {
if (!IsPaused) {
if (!OnLoop()) {
break;
}
}
Thread.Sleep(1000);
}
OnShutdown();
}
public abstract void OnBeforeThreadStart();
public abstract void OnThreadStart();
public abstract bool OnLoop();
public abstract void OnShutdown();
public abstract void OnPauseRequest();
public override string ToString() {
return stringRepresentation;
}
}
public class Test : Worker {
public override void OnBeforeThreadStart() {
Log.WriteLine(this + ": Thread about to be started...");
}
public override void OnThreadStart() {
Log.WriteLine(this + ": Thread Started!");
}
public override bool OnLoop() {
Log.WriteLine(this + ": I am doing the things...");
return true;
}
public override void OnShutdown() {
Log.WriteLine(this + ": Shutting down!");
}
public override void OnPauseRequest() {
}
}
public static class Log {
public delegate void LogDelegate(string text, string eventTime, Severity severity);
public static event LogDelegate OnWriteLine;
private static Queue<string> _pendingFileWrites = new Queue<string>();
public enum Severity {
Info,
Warning,
Error
}
public static void WriteLine(object line, Severity severity = Severity.Info) {
string eventTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
string formatted = "[" + eventTime + "]: " + line;
Console.WriteLine(formatted);
lock (_pendingFileWrites) {
_pendingFileWrites.Enqueue(formatted);
}
if (OnWriteLine != null) {
// this is the offending line:
OnWriteLine.Invoke((string)line, eventTime, severity);
}
}
public static void WriteToFile(string path) {
lock(_pendingFileWrites) {
StreamWriter sw = File.AppendText(path);
while(_pendingFileWrites.Count > 0) {
sw.WriteLine(
_pendingFileWrites.Dequeue()
);
}
sw.Close();
}
}
}
class Program {
static void Main(string[] args) {
List<Test> tests = new List<Test>();
for(int i = 0; i < 10; i++) {
Test test = new Test();
test.Start();
tests.Add(test);
}
// sleep a little bit so they do the things
Thread.Sleep(10000);
foreach (Test test in tests) {
test.ScheduleStop();
}
bool allStopped;
do {
allStopped = true;
foreach (Test test in tests) {
if (!test.IsStopped) {
allStopped = false;
break;
}
}
} while (!allStopped);
Console.WriteLine("Done!");
// a place to place a breakpoint
bool breakPointHere = true;
}
}
}
I think your original testing that lead you to believe .IsAlive would be true had some flaw in it, I tweaked your program in your question to the following to make it compile and to be able to see which thread it created.
public class Program
{
public class Test
{
Thread t;
public Test()
{
t = new Thread(ThreadFunction);
t.Name = "TestThread";
}
public void Start()
{
t.Start();
}
private void ThreadFunction()
{
Thread.Sleep(5000);
Console.WriteLine("Function Complete");
}
}
public static void Main()
{
Test test = new Test();
test.Start();
// sleep longer than my worker so it finishes
Thread.Sleep(10000);
// a place to place a breakpoint
bool breakPointHere = true;
}
}
here is a screenshot of the running threads from inside ThreadFunction
Here is a screenshot from the end of the program
Notice that there is no "TestThread" thread.
Here is a screenshot from the locals window
IsAlive is false.
Do you really need to sleep to wait for your thread to finish?
If you don't, a better and more robust solution would be using Thread.Join()
public static class Main {
public Main() {
Test test = new Test();
test.Start();
test.Join(); // Waits for test to complete
bool breakPointHere = true;
}
}
So it turns out that my issue was that my logging method was calling a UI thread function like so:
private void LogToForm(object line, string eventTime, Log.Severity severity) {
if (dataGridView_LogInfo.InvokeRequired) {
dataGridView_LogInfo.Invoke (
new Action<object, string, Log.Severity>(LogtoFormCallback),
new object[] { line, eventTime, severity }
);
} else {
LogtoFormCallback(line, eventTime, severity);
}
}
At the Invoke() line, the thread would hang forever. The solution was to replace it with BeginInvoke() instead.
EDIT: Also, my example was/is quite poor for this. I thought I didn't understand threads at a fundamental level, and that my examples would have been enough. Hopefully someone googles this though and has this same cause, and can try this solution.
I got this error and cannot understand this error.
I use win form and .net 3.5.
The problem is, this can be compiled and intermittent. Just shown today, so i guess this occur very rare (maybe once after 5000 run). I want to know what makes this error thrown, and any possible workaround.
Here is the example of how I implemented the code.
My application is multithread, and this method is singleton.
Exception type: System.ArgumentException
Exception message: Delegate to an instance method cannot have null 'this'.
Exception stack trace:
at System.MulticastDelegate.ThrowNullThisInDelegateToInstance()
at System.MulticastDelegate.CtorClosed(Object target, IntPtr methodPtr)
class Caller
{
private ClassA theA;
public Caller()
{
theA = new ClassA();
}
public void button_click()
{
theA.Execute(false);
}
public void button2_click()
{
theA.Execute( true );
}
}
interface IClassA
{
void ActionMinus();
}
class ClassA
{
public int VariableA = 0;
public void Execute( bool wait )
{
ClassB instanceB = new ClassB( this );
Thread thread = new Thread( instanceB.Action ) // error in here
{
Name = "Executor",
Priority = ThreadPriority.Highest
};
thread.Start();
if( wait )
thread.Join();
}
public void ActionMinus()
{
//someAction1
VariableA -= 2;
//someAction2
}
}
class ClassB
{
private readonly ClassA instanceA;
public ClassB( ClassA instance )
{
instanceA = instance;
}
public void Action()
{
//some other action3
instanceA.VariableA += 5;
//some other action4
instanceA.ActionMinus();
//some other action5
}
}
It looks like it works to me.
What is the context of your program?
I wrote a simple empty shell containing your code, but the program will end before the thread gets kicked off.
I had to add a Console.ReadKey() method.
Here is the whole code I used:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace DelegateToInstance {
class Program {
static void Main(string[] args) {
var obj = new Caller();
obj.button_click();
Console.ReadKey();
}
}
class Caller
{
private ClassA theA;
public Caller()
{
theA = new ClassA();
}
public void button_click()
{
theA.Execute(false);
}
public void button2_click()
{
theA.Execute( true );
}
}
interface IClassA
{
void ActionMinus();
}
class ClassA
{
public int VariableA = 0;
public void Execute( bool wait )
{
ClassB instanceB = new ClassB(this);
Thread thread = new Thread( instanceB.Action ) // error in here
{
Name = "Executor",
Priority = ThreadPriority.Highest
};
thread.Start();
if( wait )
thread.Join();
}
public void ActionMinus()
{
//someAction1
VariableA -= 2;
//someAction2
}
}
class ClassB
{
private readonly ClassA instanceA;
public ClassB( ClassA instance )
{
instanceA = instance;
}
public void Action()
{
//some other action3
instanceA.VariableA += 5;
//some other action4
instanceA.ActionMinus();
//some other action5
}
}
}
I hate downvoters, so I gave you an upvote.
So I have a simple test using Monitor.Wait with a timeout set for three seconds. It's my understanding that, when the time expires, a virtual pulse is sent to the monitor to release the wait. In my test, however, that never seems to happen. Can someone explain what's going on. Here's my test code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace BlockingMethodFoo
{
class Program
{
static void Main(string[] args)
{
WaitFoo foo = new WaitFoo();
foo.StartMethod();
Console.WriteLine("Done. Press enter");
Console.ReadLine();
}
}
public class WaitFoo
{
private object _waitObj = new object();
private string _message = string.Empty;
public void StartMethod()
{
Thread waitThread = new Thread(new ThreadStart(new Action(() => { WaitMethod(); })));
_message = string.Empty;
Console.WriteLine("Starting wait");
_message = "Time Out";
lock (_waitObj)
{
waitThread.Start();
Monitor.Wait(_waitObj, TimeSpan.FromSeconds(3));
}
Console.WriteLine(_message);
}
private void WaitMethod()
{
lock (_waitObj)
{
_message = Console.ReadLine();
Monitor.Pulse(_waitObj);
}
}
}
}
Monitor.Wait will return false if the timeout expires and it couldn't get the lock.
http://msdn.microsoft.com/en-us/library/tdc87f8y.aspx
You have to check the return of Monitor.Wait and for example throw a TimeOutException if you see fit.
When using the StartNew() method to kick off a process on a new thread, I need to figure out how to make another call into this object in that same thread (I assume this would be some sort of Join operation?).
The following example is dumbed down to illustrate the meat of what I am trying to do. I am well aware it is severely lacking in basic concurrency considerations. But I didn't want to cloud the code with all of that logic, so please forgive me on that.
The following console app shows what I am trying to accomplish. Assume on the StartNew() call a new thread with ID 9976 is created and the method invoked there. I would like the subsequent call to ProcessImmediate() in the file system watcher change event handler to be made on thread 9976 as well. As it stands, the call would share the same thread that is used for the file system watcher change event.
Can this be done, and if so, how?
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var runner = new Runner();
runner.Run();
Console.ReadKey();
}
}
public class Runner
{
private Activity _activity = null;
private FileSystemWatcher _fileSystemWatcher;
public void Run()
{
_activity = new Activity();
// start activity on a new thread
Task.Factory.StartNew(() => _activity.Go());
_fileSystemWatcher = new FileSystemWatcher();
_fileSystemWatcher.Filter = "*.watcher";
_fileSystemWatcher.Path = "c:\temp";
_fileSystemWatcher.Changed += FileSystemWatcher_Changed;
_fileSystemWatcher.EnableRaisingEvents = true;
}
private void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
// WANT TO CALL THIS FOR ACTIVITY RUNNING ON PREVIOUSLY CALLED THREAD
_activity.ProcessImmediate();
}
}
public class Activity
{
public void Go()
{
while (!Stop)
{
// for purposes of this example, magically assume that ProcessImmediate has not been called when this is called
DoSomethingInteresting();
System.Threading.Thread.Sleep(2000);
}
}
protected virtual void DoSomethingInteresting() { }
public void ProcessImmediate()
{
// for purposes of this example, assume that Go is magically in its sleep state when ProcessImmediate is called
DoSomethingInteresting();
}
public bool Stop { get; set; }
}
}
* UPDATE *
Thanks for the excellent responses. I took Mike's suggestion and implemented it for my console app. Below is the full working code which also includes the use of a cancellation token. I post this in case someone else might find it useful.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var runner = new Runner();
runner.Run();
Console.ReadKey();
runner.Stop();
Console.ReadKey();
}
}
public class Runner
{
private Activity _activity = null;
private FileSystemWatcher _fileSystemWatcher;
private CancellationTokenSource _cts = new CancellationTokenSource();
public void Stop() { _cts.Cancel(); }
public void Run()
{
_activity = new Activity();
// start activity on a new thread
var task = new Task(() => _activity.Go(_cts.Token), _cts.Token, TaskCreationOptions.LongRunning);
task.Start();
_fileSystemWatcher = new FileSystemWatcher();
_fileSystemWatcher.Filter = "*.watcher";
_fileSystemWatcher.Path = "C:\\Temp\\FileSystemWatcherPath";
_fileSystemWatcher.Changed += FileSystemWatcher_Changed;
_fileSystemWatcher.EnableRaisingEvents = true;
}
private void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
// WANT TO CALL THIS FOR ACTIVITY RUNNING ON PREVIOUSLY CALLED THREAD
_activity.ProcessImmediate();
}
}
public class Activity : IDisposable
{
private AutoResetEvent _processing = new AutoResetEvent(false);
public void Go(CancellationToken ct)
{
Thread.CurrentThread.Name = "Go";
while (!ct.IsCancellationRequested)
{
// for purposes of this example, magically assume that ProcessImmediate has not been called when this is called
DoSomethingInteresting();
_processing.WaitOne(5000);
}
Console.WriteLine("Exiting");
}
protected virtual void DoSomethingInteresting()
{
Console.WriteLine(string.Format("Doing Something Interesting on thread {0}", Thread.CurrentThread.ManagedThreadId));
}
public void ProcessImmediate()
{
// for purposes of this example, assume that Go is magically in its sleep state when ProcessImmediate is called
_processing.Set();
}
public void Dispose()
{
if (_processing != null)
{
_processing.Dispose();
_processing = null;
}
}
}
}
First, you should use TaskCreationOptions.LongRunning if you are creating a task that will not complete quickly. Second, use an AutoResetEvent to signal the waiting thread to wake up. Note that below ProcessImmediate will return before DoSomethingInteresting has completed running on the other thread. Example:
using System.Threading;
public class Activity : IDisposable
{
private AutoResetEvent _processing = new AutoResetEvent(false);
public void Go()
{
while (!Stop)
{
// for purposes of this example, magically assume that ProcessImmediate has not been called when this is called
DoSomethingInteresting();
_processing.WaitOne(2000);
}
}
protected virtual void DoSomethingInteresting() { }
public void ProcessImmediate()
{
_processing.Set();
}
public bool Stop { get; set; }
public void Dispose()
{
if (_processing != null)
{
_processing.Dispose();
_processing = null;
}
}
}
User mike has given a better solution, which will be appropriate when you like to call the same method immediately. If you want to call a different methods immediately I'll expand mike's answer to achieve that.
using System.Threading;
public class Activity : IDisposable
{
private AutoResetEvent _processing = new AutoResetEvent(false);
private ConcurrentQueue<Action> actionsToProcess = new ConcurrentQueue<Action>();
public void Go()
{
while (!Stop)
{
// for purposes of this example, magically assume that ProcessImmediate has not been called when this is called
DoSomethingInteresting();
_processing.WaitOne(2000);
while(!actionsToProcess.IsEmpty)
{
Action action;
if(actionsToProcess.TryDeque(out action))
action();
}
}
}
protected virtual void DoSomethingInteresting() { }
public void ProcessImmediate(Action action)
{
actionsToProcess.Enqueue(action);
_processing.Set();
}
public bool Stop { get; set; }
public void Dispose()
{
if (_processing != null)
{
_processing.Dispose();
_processing = null;
}
}
}
To execute different methods on the same thread you can use a message loop that dispatches incoming requests. A simple option would be to use the event loop scheduler of the Reactive Extensions and to "recursively" schedule your Go() function - if in the mean time a different operation is scheduled it would be processed before the next Go() operation.
Here is a sample:
class Loop
: IDisposable
{
IScheduler scheduler = new EventLoopScheduler();
MultipleAssignmentDisposable stopper = new MultipleAssignmentDisposable();
public Loop()
{
Next();
}
void Next()
{
if (!stopper.IsDisposed)
stopper.Disposable = scheduler.Schedule(Handler);
}
void Handler()
{
Thread.Sleep(1000);
Console.WriteLine("Handler: {0}", Thread.CurrentThread.ManagedThreadId);
Next();
}
public void Notify()
{
scheduler.Schedule(() =>
{
Console.WriteLine("Notify: {0}", Thread.CurrentThread.ManagedThreadId);
});
}
public void Dispose()
{
stopper.Dispose();
}
}
static void Main(string[] args)
{
using (var l = new Loop())
{
Console.WriteLine("Press 'q' to quit.");
while (Console.ReadKey().Key != ConsoleKey.Q)
l.Notify();
}
}