EDIT: Question answered. Answer explained perfectly by Igor. (Thank you!)
Question: How do I access/control a thread from another class in the same program?
I'm will be having multiple threads active (not all at once) and I need to check if one is active (that is not the main thread).
I am programming in C# and I am trying to use threading.
I have 2 classes, my thread starts in the main class calling a function in the other class. In my other class I want to see if "thread.isAlive == true" but I think it isn't publicly available. I don't know the syntax/code to be able to use the thread from another class? I'm struggling to get it working.
I can call the other class, but I can't call the thread between classes. (Can't declare a thread outside of a class)
The error thrown is:
Error 1 The name 'testThread' does not exist in the current context
Example code:
//Headers
using System.Threading;
using System.Threading.Tasks;
namespace testProgram
{
public class Form1 : Form
{
public void main()
{
//Create thread referencing other class
TestClass test = new TestClass();
Thread testThread = new Thread(test.runFunction)
//Start the thread
testThread.Start();
}//Main End
}//Form1 Class End
public class TestClass
{
public void runFunction()
{
//Check if the thread is active
//This is what I'm struggling with
if (testThread.isAlive == true)
{
//Do things
}//If End
}//runFunction End
}//testClass End
}//Namespace End
Thanks for reading!
-Dave
if (System.Threading.Thread.CurrentThread.isAlive == true) { ... }
But you are doing this: "Is the thread, in which I am executing, running? Yes it is running since the code that is doing the check is in it and I am currently in that code."
But if you insist:
public class Form1 : Form
{
public void main()
{
//Create thread referencing other class
TestClass test = new TestClass();
Thread testThread = new Thread(test.runFunction)
test.TestThread = testThread;
//Start the thread
testThread.Start();
}//Main End
}//Form1 Class End
public class TestClass
{
public Thread TestThread { get; set; }
public void runFunction()
{
//Check if the thread is active
if (TestThread != null && TestThread.isAlive == true)
{
//Do things
}//If End
}//runFunction End
}//testClass End
Related
I have the class ComputationService which is the wrapper of the old legacy COM object. This COM object cannot have multiple instances because of how its implemented.
In the application, there are two buttons (for simplification) when clicked a new Task runs which use a ComputationService these tasks are kind of long-running tasks so you can click on the second button when the first one is in the process of computing. That's where the problem occurs because I can't let both threads use the ComputationService so I decided to use Mutex to allow only one instance of ComputationService at the time.
What I have:
public class ComputationService : IComputationService
{
public ComputationService()
{
_mutex = new Mutex(true, "AwesomeMutex");
_mutex.WaitOne();
}
public void Dispose()
{
_mutex.ReleaseMutex();
}
}
and then two places where I use it:
public Task Compute1()
{
return Task.Run(() =>
{
foreach (var item in items)
{
using (var service = _computationFactory()) // new instance of ComputationService
{
//Do some work
}
}
});
}
public Task Compute2()
{
return Task.Run(() =>
{
foreach (var item in items)
{
using (var service = _computationFactory()) // new instance of ComputationService
{
//Do some other work
}
}
});
}
What I get when I am debugging to console:
Mutex created by Thread: 18
Wait, thread: 18
Do Work, thread: 18
Mutex created by Thread: 20
Wait, thread: 20
Mutex release by thread: 18
Mutex created by Thread: 18
Wait, thread: 18
Do Work, thread: 18
Mutex release by thread: 18
Then of course AbandonedMutexException() occurs on Thread 20.
I tried to use lock in the constructor of ComputationService but did not work.
Can you please help me, what I am doing wrong and how to fix it?
Problem is here:
_mutex = new Mutex(true, "AwesomeMutex");
_mutex.WaitOne();
You are passing true as first argument, named initiallyOwned. If you pass true there - that means IF mutex with such name did not exist before and is created as a result of this constructor - current thread now owns it. You don't check if mutex was created as a result of this call, and actually there is even no way to check that when using this constructor overload. So never ever pass true if using this constructor.
If you want to utilize initiallyOwned - then use another overload, which actually tells you whether mutex was created as a result of this constructor:
_mutex = new Mutex(true, "AwesomeMutex", out var createdNew);
Now, if createdNew returned true - you do NOT need to call _mutex.WaitOne(), because as per above - current thread already owns the mutex. That's what happens in your case - sometimes you already own the mutex and then you call _mutex.WaitOne(). Now to release it you would have to call Release() twice, which you never do.
Alternatively, just pass false, then wait:
_mutex = new Mutex(false, "AwesomeMutex");
_mutex.WaitOne();
If the whole thing happens in the same process, then you don't need global mutex (which you now have because you pass a name) - you can do fine with a local one:
public class ComputationService : IDisposable {
// one static instance
private static readonly Mutex _mutex = new Mutex();
public ComputationService()
{
_mutex.WaitOne();
}
public void Dispose() {
_mutex.ReleaseMutex();
}
}
There are other improvements that can be made, but they are out of scope of this question.
As mentioned in comments - in single process lock (Monitor.Enter \ Monitor.Exit) will be faster and achieve the same result in your case:
public class ComputationService : IDisposable {
// one static instance
private static readonly object _mutex = new object();
public ComputationService()
{
Monitor.Enter(_mutex);
}
public void Dispose() {
Monitor.Exit(_mutex);
}
}
I have a Class file to perform certain function , for example
public class clsFunction
{
public DataTable FunctionOne()
{
//some code
}
public void FunctionTwo()
{
//Some Code
}
}
SecondClass is use to call function from clsFunction , and this main class in running on a console program with multiple thread.
public class SecondClass
{
public void ThreadOne()
{
while(true){DataTable dt = new clsFunction().FunctionOne;}
}
public void ThreadTwo()
{
while(true){new clsFunction().FunctionTwo();}
}
}
class Main
{
static void Main (string[] args)
{
//Thread to start SecondClass.ThreadOne
//THread to start SecondClass.ThreadTwo
}
}
My concern is will my class value reinitialize to default value when I call new clsFunction() each time. for example , thread two may running it own value , when thread one is call , will all the thread two value change to it default value ?
Maybe you don't understand what new does. It creates an object. It's purpose is not to initialize something that already exists. Objects are independent.
Creating an object has no influence on any other object, except of course if the constructor does something to influence other objects.
Forgive me, I'm learning C# and object-oriented programming. I am running two threads. Thread #2 calls a different class method. This method assigns an object's data value. Thread #1 unsuccessfully attempts to access the object's data value that Thread #2 assigned. The object's data value in Thread #1 is null. How do I access this object and all its assigned data values? I basically want to save the data variables from Thread #2 classes and access them from a Thread #1 class. It appears an object and it's data member values generated in a Thread #2 class are null when I leave the class and then try to access the same object in a Thread #1 class. Can I still save the instantiated object values in my example or should I declare things as static? Below is some of my code to illustrate my problem. Thank you for anyone that can recommend or illustrate how to resolve this.
// this is a main operating class that: 1) starts two threads and 2) trys to access the Thread #2 Lru_SetChanFreq class object data from Thread #1 Lru_operations class
public class Lru_operation
{
[STAThread]
static void Main()
{
// starts a separate thread #2
Lru_Listen LruListen1 = new Lru_Listen();
Thread LruListenThread = new Thread(new ThreadStart(LruListen1.ListenForAag));
LruListenThread.Start();
while(!LruListenThread.IsAlive)
;
Thread.Sleep(1);
// follows the main thread #1
Lru_operation LruOpX = new Lru_operation();
LruOpX.LruOperation();
}
// this is where main thread #1 operates
public void LruOperation()
{
// create object to access object data from thread #2 Lru_SetChanFreq class
Lru_SetChanFreq SetChFrq = new Lru_SetChanFreq();
try
{
// do stuff
// ERROR: SetChFrq.LruSetFrq.RxFreq2 = null and then catches an exception to go below.
// Why is this happening if Thread #2 previously sets RxFreq2 = 405.1?
Console.WriteLine("LruSetFrq.RxFreq2 = {0}", SetChFrq.LruSetFrq.RxFreq2);
// do more stuff
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "connection terminated",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
// this is called from thread #2. It's object is used by thread #1
public class Lru_SetChanFreq
{
#region fields
private string rxFreq2;
private Lru_SetChanFreq mLruSetFrq;
#endregion fields
#region Properties
public Lru_SetChanFreq LruSetFrq
{
get { return mLruSetFrq; }
set { mLruSetFrq = value; }
}
public string RxFreq2
{
get { return rxFreq2; }
set { rxFreq2 = value; Console.WriteLine("rxFreq2 = {0}", rxFreq2); }
}
#endregion Properties
#region methods
public Lru_SetChanFreq()
{
}
public void SetFreq()
{
mLruSetFrq = new Lru_SetChanFreq();
mLruSetFrq.RxFreq2 = "405.1";
// I confirmed that LruSetFrq.RxFreq2 = 405.1
Console.WriteLine("LruSetFrq.RxFreq2 = {0}", LruSetFrq.RxFreq2);
// do stuff
}
#endregion methods
}
// this is starting point of thread #2
public class Lru_Listen
{
#region Fields
// stuff
#endregion Fields
#region Properties
// stuff
#endregion Properties
#region Methods
public void ListenForAag()
{
// do stuff
LruListenAccReq();
}
public void LruListenAccReq()
{
// do stuff
LruShowRequestData(request);
}
public void LruShowRequestData(// stuff )
{
Lru_SetChanFreq SetChanFreq = new Lru_SetChanFreq();
SetChanFreq.SetFreq(); // calls to another class method
}
#endregion Methods
}
}
Your 2 Threads each make an instance of Lru_SetChanFreq . The 2 instances are not related or coupled. Setting a value on one thread (SetChanFreq.SetFreq()) has no bearing on the other thread.
A few points:
Try to pick meaningful, readable names. Prefixes like Lru_ have a negative impact on readability.
Study the meaning of object-instance (vs static) first. Leave threading alone until you have a good grasp of objects and memory management.
In the end you probably won't want to use Threads at all, ThreadPool and Task are more efficient and convenient.
Your issue is that you are initializing and accessing distinct Lru_SetChanFreq instances in your two threads. You should initialize just one, assign it to a class field, and then access the same instance from the other thread. Here is a trimmed-down version of your code that does that:
public class Lru_operation
{
[STAThread]
static void Main()
{
Lru_Listen LruListen1 = new Lru_Listen();
// Run LruListen1 on Thread 2
Thread LruListenThread = new Thread(new ThreadStart(LruListen1.ListenForAag));
LruListenThread.Start();
// Wait for its operation to complete
// There is no need to wait for the thread to terminate
LruListen1.readyEvent.WaitOne();
// Read the Lru_SetChanFreq initialized from LruListen1,
// and continue processing it on Thread 1
Lru_operation LruOpX = new Lru_operation();
LruOpX.LruOperation(LruListen1.SetChanFreq);
}
public void LruOperation(Lru_SetChanFreq setChanFreq)
{
// Access the original Lru_SetChanFreq instance received as parameter
}
}
// this is starting point of thread #2
public class Lru_Listen
{
// Declare Lru_SetChanFreq as a field so as to access it externally
internal Lru_SetChanFreq SetChanFreq;
// Our thread synchronization event
internal ManualResetEvent readyEvent = new ManualResetEvent(false);
public void LruShowRequestData(// stuff )
{
this.SetChanFreq = new Lru_SetChanFreq();
SetChanFreq.SetFreq(); // calls to another class method
// Signal that we are ready
readyEvent.Set();
}
}
Update: I've edited my code to introduce proper thread synchronization (to replace the OP's while (LruListenThread.IsAlive) and Thread.Sleep(1)). This consists of three parts:
Creating a ManualResetEvent instance that can be accessed by both threads.
Calling WaitOne from Thread 1, in order to make it wait.
Calling Set from Thread 2 once it completes initializing your Lru_SetChanFreq, thereby signalling to Thread 1 that it may proceed.
I want to access a static WebBrowser from different threads.
Here is my sample code:
public partial class MainFrame : Form
{
public static WebBrowser webBrowser = new WebBrowser();
public MainFrame()
{
InitializeComponent();
}
}
class Job
{
public void Process()
{
MainFrame.webBrowser.Navigate("http://www.google.com");
while (MainFrame.webBrowser.ReadyState != WebBrowserReadyState.Complete)
{
Thread.Sleep(1000);
Application.DoEvents();
}
}
}
For simplicity suppose I have 2 threads. Thread 1 calls Process() function and waits for it to finish, so at this stage webBrowser should be in Complete WebBrowserReadyState mode.
10 seconds after thread 1 is finished, Thread 2 calls Process() function. At this moment If i debug my code and put a BreakPoint at the first line of Process() function and watch MainFrame.webBrowser variable I would see this:
In another words it's somehow inaccessible. Anyone knows any solution to this issue?
Additional info: 10 seconds after thread 1 is
finished, If I call Thread 1 again, then everything looks fine.
You cannot directly call WebBrowser control's methods or properties from a thread the control was not created on. You'd need to proxy such calls into the control's parent thread. One way of doing this is with BeginInvoke, but it is asynchronous.
If you really need to do it synchronously, you could use SynchronizationContext.Send, like this:
public partial class MainFrame : Form
{
public static WebBrowser webBrowser = new WebBrowser();
public static System.Threading.SynchronizationContext mainThreadContext = System.Threading.SynchronizationContext.Current;
public MainFrame()
{
InitializeComponent();
}
}
class Job
{
public void Process()
{
mainThreadContext.Send(delegate
{
MainFrame.webBrowser.Navigate("http://www.google.com");
}, null);
bool ready = false;
while (!ready)
{
mainThreadContext.Send(delegate
{
ready = MainFrame.webBrowser.ReadyState != WebBrowserReadyState.Complete;
}, null);
Thread.Sleep(1000);
// if you don't have any UI on this thread, DoEvent is redundant
Application.DoEvents();
}
}
}
Anyway, the above code doesn't looks like a good design to me. What are you trying to achieve? There might be a better way of do it. Perhaps, you can just use WebBrowser.DocumentCompleted event?
I've got a program that executes a method through a Thread.Start. The method has a return value that I'd like to get access to. Is there a way to do this? Here's a sampling...
var someValue = "";
Thread t = new Thread(delegate() { someValue = someObj.methodCall(); });
t.Start();
while (t.isAlive) Thread.Sleep(1000);
// Check the value of someValue
So once the while loop ends, the someValue should be set - but because it's executed in another thread it doesn't get set. Is there a simple way to get access to it?
When the caller and the threaded method share a variable, you already have access to it - once the thread has completed, you just check someValue.
Of course, you have to know when the threaded method is complete for this to be useful. At the bottom, there are two ways to do this:
Send a callback into the threaded method that it can execute when it's finished. You can pass your callback method someValue. You can use this technique if you don't care when the callback executes.
Use a WaitHandle of some kind (or Thread.Join). These tell you when a resource is ready or an event has completed. This technique is useful if you want to start a thread, do something else, then wait until the thread completes before proceeding. (In other words, it's useful if you want to sync back up with the thread, just not right away.)
I can't recreate your issue, I've got the same code and I'm seeing the expected result. If you're just going to sleep the current thread until it's complete you could just call .Join() on the thread and wait to be sure it's done executing.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string someValue = "";
private void Form1_Load(object sender, EventArgs e)
{
Thread t = new Thread(delegate() { someValue = "asdf"; });
t.Start();
t.Join();
//while (t.IsAlive) Thread.Sleep(1000);
System.Diagnostics.Debug.Print(someValue);
}
}
One of possible methods to return a value from a Thread is to use a context class as a parameter object. It can be used to pass parameters and retrieve the result as well.
If on the other hand you could use a BackgroundWorker class, it has already a dedicated Result object - that works the same way. But BackgroundWorker cannot be used for some purposes (for instance, it doesn't support STA Apartment State).
Keep in mind that you shouldn't read from ctx.Result until the thread is finished (i.e. t.IsAlive == false).
void runThread()
{
ThreadContext ctx = new ThreadContext();
ctx.Value = 8;
Thread t = new Thread(new ParameterizedThreadStart(MyThread));
//t.SetApartmentState(ApartmentState.STA); // required for some purposes
t.Start(ctx);
// ...
t.Join();
Console.WriteLine(ctx.Result);
}
private static void MyThread(object threadParam)
{
ThreadContext context = (ThreadContext)threadParam;
context.Result = context.Value * 4; // compute result
}
class ThreadContext
{
public int Value { get; set; }
public int Result { get; set; }
}
You can retrieve data from Thread function using delegate callback. The delegate can serve as a bridge between thread and the caller. For example:
public delegate void DelReturnValue(string value);
public class SayHello
{
private string _name;
private DelReturnValue _delReturnValue;
public SayHello(string name, DelReturnValue delReturnValue)
{
_name = name;
_delReturnValue = delReturnValue;
}
public void SayHelloMethod()
{
_delReturnValue(_name);
}
}
public class Caller
{
private static string _returnedValue;
public static void ReturnValue(string value)
{
_returnedValue = value;
}
public static void Main()
{
DelReturnValue delReturnValue=new DelReturnValue(ReturnValue);
SayHello sayHello = new SayHello("test", delReturnValue);
Thread newThread = new Thread(new ThreadStart(sayHello.SayHelloMethod));
newThread.Start();
Thread.Sleep(1000);
Console.WriteLine("value is returned: " + _returnedValue);
}
}
Have a look at the Asynchronous Programming Model.
In one of the common patterns the model describes, your class will expose BeginXXX and EndXXX methods. The former starts the asynchronous operation and returns an IAsyncResult object. The latter accepts the IAsyncResult object as an argument, blocks the calling thread until the operation is complete and returns the required value.