I´m currently figuring out threads and how to work with them.
At the same time Im working on my understanding on Events/Global Events (just for context).
I defined a thread inside a object with the function the thread will use on thread.Start().
internal class Name
{
private Thread testthread;
private EventWaitHandle globalEvent;
private Eventstest evente = new Eventstest(); //Just to add some methods
public Name(Thread testthread, EventWaitHandle globalEvent)
{
this.testthread = testthread;
this.globalEvent = globalEvent;
}
public void Execute()
{
bool terminate = false;
bool eventset = false;
bool rdy = false;
while (!terminate)
{
if (evente.CheckSysEvent(globalEvent))
{
eventset = true; //This is just to check with debugger if the event was raised elsewhere
}
Thread.Sleep(100);
}
}
}
So now, like in this example in a Windows Forms App, Im trying to set an instance of this class while setting the instance of the thread at the same time (with the work method the should run later on).
Im struggling with this part here.
private void btn_runThread_Click(object sender, EventArgs e)
{
threadClass = new Name(new Thread(ProblemHere), globalEvent);
threadClass.Execute();
}
This is a button which starts the thread with the work its supposed to do.
The variable threadClass is just the initialization in the forms1.cs:
Name threadClass;
I know that it wants a delegate to pass the method which the thread should use on start.
I tried pretty much anything I found and cant make it work.
I cant just pass the method, that doesnt work.
And the stuff I found in the c# documentation is pretty much just passing the method, as far as I understood it.
Which is propably wrong.
And I just noticed, how am I able to actually call on that property/thread.start if its only created on runtime?
Not a full solution, but a bump to get you going:
What I would suggest is a little refactor like this
internal class Name
{
private Thread testthread;
private EventWaitHandle globalEvent;
private Eventstest evente = new Eventstest(); //Just to add some methods
public Name(EventWaitHandle globalEvent)
{
this.testthread = new Thread(Execute); // Creates a Thread, that is directed to execute `Execute`
this.globalEvent = globalEvent;
this.testthread.Start(); // Tells the framework to schedule the thread for execution.
}
private void Execute()
{
bool terminate = false;
bool eventset = false;
bool rdy = false;
while (!terminate)
{
if (evente.CheckSysEvent(globalEvent))
{
eventset = true; //This is just to check with debugger if the event was raised elsewhere
}
Thread.Sleep(100);
}
}
}
And in the Button handler just do
private void btn_runThread_Click(object sender, EventArgs e)
{
threadClass = new Name(globalEvent);
}
Mind that there are still a good portion of mistakes and ooopsies, but at least, this will keep your GUI thread running and you may gain an understanding to go on from here.
A totally different approach (if you are willing to consider it) would be to use a System.Windows.Forms.Timer instead. With that you can have a method called every X time, which would check the state of the globalevent as you are trying to get the thread to doing. The timer, however, makes this a little more convenient.
The typical way would be to create the thread in the constructor, as described in the answer by Fildor.
But I want to point out that using the Thread object directly is rarely the correct way to do things since there are other tools more suited for whatever you are tryibng to do:
If you want to do something compute heavy on a background thread once, and update the UI after it has been done. Use Task.Run and async/await
If you want to do something every X seconds. Use a timer. There are both timers that run on the main thread or a background thread, see differences between timers.
If you want to run an compute heavy operation in parallel, use Parallel.For, possibly in combination with Task.Run.
If you want to call IO intensive methods without freezing the UI, use async/await in combination with the appropriate Async methods.
If you want to create a producer/consumer or other processing pipeline there is the DataFlow library
Related
I just started programming after taking a long break and am running into a little issue.
I am using VS2013 Desktop and am creating this as a GUI program.
My problem is that I created a working random number generator when the method used to call the logic method runs once. The number(s) gets generated, text updated and all is good. When it goes into a loop, it doesn't update the text property of the object I'm modifying until it finishes the entire loop or gets broken. The program basically hangs when I run it when the loop gets executed and I have to force it to close.
At the moment I would like to set the generator to run infinitely in the background until I press another button to stop it.
I am new to programming and this probably has all sorts of issues with it so I would be grateful for any feedback on structure and other practices if anything is out of order as well.
Here is the code:
Form1.cs
// Global
bool boolLooper;
// Setting up the random number generator
private string RandomNumber()
{
RandomNumber rndNumber = new RandomNumber();
string strRandNumber = Convert.ToString(rndNumber.RandomInt(1000, 9999999));
return strRandNumber;
}
// TEST - used in buttonclick event
private void TextUpdates()
{
while (BoolLooper == true)
{
txtID1.Text = RandomNumber();
//txtName1.Text = RandomNumber();
//txtSize1.Text = RandomNumber();
//txtKey1.Text = RandomNumber();
//txtType1.Text = RandomNumber();
}
}
//-----------------------------
// Form - Button Clicks
//-----------------------------
// Button - Activate
private void btnActivate_Click(object sender, EventArgs e)
{
BoolLooper = true;
TextUpdates();
//// Update text once
//txtID1.Text = RandomNumber();
//txtName1.Text = RandomNumber();
//txtSize1.Text = RandomNumber();
//txtKey1.Text = RandomNumber();
//txtType1.Text = RandomNumber();
}
// Button - Stop/Deactivate
private void btnDeactivate_Click(object sender, EventArgs e)
{
BoolLooper = false;
}
//-----------------------------
// Properties
//-----------------------------
public bool BoolLooper
{
get { return boolLooper; }
set { boolLooper = value; }
}
RandomNumber.cs
private static readonly Random intRandom = new Random();
private static readonly object syncLock = new object();
public int RandomInt(int minNum, int maxNum)
{
lock (syncLock)
{
// synchronize
return intRandom.Next(minNum, maxNum);
}
}
For the RandomNumber class, I found a great post on this site found here which I will give credit to it's author: https://stackoverflow.com/a/768001
You're running this code on the same thread as the UI. Since it's single-threaded, the UI can't respond because it's busy running your loop. You'll want to off-load this to a separate thread or in some way as a separate asynchronous operation. That thread/operation would then just need to tell the UI of updates when it has them.
A simple example of this would be to use a BackgroundWorker object.
Note in the example on that page where the BackgroundWorker exposes an event which can be used to update UI elements:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
resultLabel.Text = (e.ProgressPercentage.ToString() + "%");
}
There are other possible approaches as well. You could create a Thread manually and try to synchronize it manually, but that comes with other potential issues as well. And there really isn't a need to get that complex here.
Do you need the TextBox to be constantly updating? Or just updating every once in a while? If there's some discernible time period between updates (one second?) then you can use a Timer to schedule the code to take place periodically. The structure is similar to the BackgroundWorker in that there's an event exposed which would be used to update the UI.
All your code is being executed on the UI thread. So you're stuck in your while loop, and the form isn't responding to the button click (which sets your while loop flag back to false). This is what we call a blocking call. It's blocking the UI from continuing.
Typically in situations like this, you would want to look into threading. However, based on your code. I'd look into a timer, and have it tick every second or so. They're very easy to implement and you can remove the complexity of your while loop and just execute the random number generation and the assigning it to your UI controls. (This also makes it so that you don't have to marshal from a background thread back onto your UI thread.)
For more information on a timer:
System.Windows.Forms.Timer
You basically need to run each call to generate a new number asynchronously. Using the .NET Framework, there are several ways to achieve that, but I prefer to use the Task class. You could do something like this:
public Task RunAsynchronously(Action method)
{
return Task.Factory.StartNew(method);
}
...
RunAsynchronously(() => MethodThatGeneratesRandomNumber());
Each time this is called, the method execution will run asynchronously.
if you are using .NET 4.5, update the TextUpdates method to use the async/await call like in the example below
private async void TextUpdates()
{
await Task.Run(() =>
{
while (BoolLooper)
{
txtID1.Invoke((MethodInvoker)(() => txtID1.Text = RandomNumber()));
//txtName1.Text = RandomNumber();
//txtSize1.Text = RandomNumber();
//txtKey1.Text = RandomNumber();
//txtType1.Text = RandomNumber();
}
});
}
You are creating new instance of a RandomNumber class each time. Just make it a member of your class. Like :
// Global
bool boolLooper;
//Random number generator
RandomNumber rndNumber = new RandomNumber();
and don't need to create new instance in method RandomNumber , just change it to this:
private string RandomNumber()
{
string strRandNumber = Convert.ToString(rndNumber.RandomInt(1000, 9999999));
return strRandNumber;
}
UPDATE: I've read a bit about Application.DoEvents() after comment, so use Invokes, await calls of Tasks, others, but not this.
The code in question
public void StartPlaying()
{
ThreadPool.QueueUserWorkItem(ignoredState =>
{
while (_playlist.Count > 0)
{
var audioFile = _playlist.Dequeue();
if (StartedPlaying != null)
StartedPlaying(this, new TypedAudioFileEventArgs(audioFile));
audioFile.SoundPlayer.PlaySync();
audioFile.SoundPlayer.Dispose();
if (StoppedPlaying != null)
StoppedPlaying(this, new TypedAudioFileEventArgs(audioFile));
}
});
}
and my test:
[TestMethod()]
public void StartPlayIsCalledTwice_OnlyRunningOnce()
{
int timeBetweenPlays = 0;
var target = new TypedAudioFilePlayer(timeBetweenPlays);
target.AddFile(TypedAudioFileCreator.CreateWord(1, "bl"));
target.StartedPlaying += StartedPlaying_Once;
target.StartPlaying();
target.StartPlaying();
}
private bool _once = false;
private void StartedPlaying_Once(object sender, TypedAudioFileEventArgs e)
{
if (!_once)
_once = true;
else
Assert.Fail("Should not be called more than once!");
}
I believe my unit test should fail, judging by the MSDN description of ThreadPool.QueueUserWorkItem:
Queues a method for execution. The method executes when a thread pool thread becomes available.
The default ThreadPool size is 512, so two threads should immediately be available to process the StartPlaying call. I believe my code should fail since I haven't provided any safeguards from race conditions in which both threads can access the same resource.
What's happening here?
Because the StartedPlaying event is only raised if StartPlaying is called when there are items to play.
_playlist.Dequeue(); dequeues the file you enqueue. Therefore the second time you get to while (_playlist.Count > 0) it will immediately fail, passing the second call to StartPlaying straight through without raising the event.
Also, as Bruno Silva points out, the thread spawned by the second call to StartPlaying may not have a chance to execute anything before the test exits.
For what it's worth, there are about a million at least 2 threading mistakes in this code also:
// Where did _playlist come from? Is it shared state among the player threads?
// If so, all access to it should be in locks, since queues are not thread safe
while (_playlist.Count > 0)
// Both of these start threads and then immediately return.
// The test will probably exit before either of those threads do anything much
target.StartPlaying();
target.StartPlaying();
}
If you want to properly unit test, you need to define preconditions, expectations, actions, and postconditions:
Preconditions: you have an initialized TypedAudioFilePlayer with one file queued:
var target = new TypedAudioFilePlayer(timeBetweenPlays);
target.AddFile(TypedAudioFileCreator.CreateWord(1, "bl"));
Expectations: The StartedPlaying event will be raised only once if StartPlaying is called twice
target.StartedPlaying += StartedPlaying_Once;
Actions: The StartPlaying method will be called twice:
target.StartPlaying();
target.StartPlaying();
Postconditions: The StartedPlaying event was only raised once:
private bool _once = false;
private void StartedPlaying_Once(object sender, TypedAudioFileEventArgs e)
{
if (!_once)
_once = true;
else
Assert.Fail("Should not be called more than once!");
}
Now, your test succeeds. That's not good in this case, because of what I explain above. You need to get your test to a failing state by eliminating the queue bug and race condition, then work on making the test pass the right way.
It seems that you are working with a shared resource between two threads so once might not be set to true when the Play is called for the second time. You can use a lock to allow executing part of your code by one thread at a time :
private readonly object lock_object=new object();
private void StartedPlaying_Once(object sender, TypedAudioFileEventArgs e)
{
lock(lock_object)
{
if (!_once)
_once = true;
else
Assert.Fail("Should not be called more than once!");
}
}
Could those be failing outside the text execution? Your test ends right after you queue the item so I'm not sure what is happening to those threads when the test method ends its execution. Have you tried using WaitHandle to wait for the them to finish inside the test?
See http://msdn.microsoft.com/en-us/library/system.threading.waithandle.aspx for an example.
I want to build a windows Service, which should execute different methods at different times. Its not about accuracy at all.
Im using a system.timers.timer, and regulate the different methods to be executed within the Eventhandler-method with counters. Thats working allright that far.
All of the methods are accessing a COM-port, making it neccessary to grant acceess-rights to only one method at a time. But since the methods can take some time to finish, the timer might tick again and want to execute another method while the COM-port is still being occupied. In this case, the event can and should just be dismissed.
Simplified down to one method, my elapsedEventHandler-method looks something like the following (try-catch and the different methods excluded here)
Note: While this is running perfectly on my Win7 x64, it struggles on a Win7 x86 machine with pretty much the very same software installed, whenever the method to be executed takes a long time. The timer wont tick any more, no Exception is thrown. Nothing! my question now is: Am I doing the part with access-control and the timer right, so that i can focus on other things? Im just not that familiar with timers and especially threading
private static int m_synchPoint=0;
private System.Timers.Timer timerForData = null;
public MyNewService()
{
timerForData = new System.Timers.Timer();
timerForData.Interval = 3000;
timerForData.Elapsed += new ElapsedEventHandler(Timer_tick);
}
//Initialize all the timers, and start them
protected override void OnStart(string[] args)
{
timerForData.AutoReset = true;
timerForData.Enabled = true;
timerForData.Start();
}
//Event-handled method
private void Timer_tick(object sender, System.Timers.ElapsedEventArgs e)
{
////safe to perform event - no other thread is running the event?
if (System.Threading.Interlocked.CompareExchange(ref m_synchPoint, 1, 0) == 0)
{
//via different else-ifs basically always this is happening here, except switching aMethod,bMethod...
processedevent++;
Thread workerThread = new Thread(aMethod);
workerThread.Start();
workerThread.Join();
m_synchPoint=0;
}
else
{
//Just dismiss the event
skippedevent++;
}
}
Thank you very much in advance!
Any help is greatly appreciated!
I would recommend using System.Threading.Timer for this functionality. You can disable the timer when it executes, process your data, then re-enable the timer.
EDIT:
I think it makes more sense to use System.Threading.Timer because there isn't really a reason you need to drop the timer on a design surface, which is pretty much the only reason to use System.Timers.Timer. I really wish MS would remove it anyways, it's wrapping System.Threading.Timer which isn't all that difficult to use in the first place.
Yes, you do risk a problem with re-entrancy which is why I specified to change the timeout toTimeout.Infinite. You won't have this re-entrancy problem if you construct the timer with Timeout.Infinite.
public class MyClass
{
private System.Threading.Timer _MyTimer;
public MyClass()
{
_MyTimer = new Timer(OnElapsed, null, 0, Timeout.Infinite);
}
public void OnElapsed(object state)
{
_MyTimer.Change(Timeout.Infinite, Timeout.Infinite);
Console.WriteLine("I'm working");
_MyTimer.Change(1000, Timeout.Infinite);
}
}
If you want just skip method invocation while previous method didn't finish just use Monitor.TryEnter(lockObject) before calling your method.
EDIT:
Here's an example -
public class OneCallAtATimeClass
{
private object syncObject;
public TimerExample()
{
syncObject = new object();
}
public void CalledFromTimer()
{
if (Monitor.TryEnter(syncObject);)
{
try
{
InternalImplementation();
}
finally
{
Monitor.Exit(syncObject);
}
}
}
private void InternalImplementation()
{
//Do some logic here
}
}
You can try this:
When the timer fires, disable the timer.
When the task is complete, re-enable the timer...possibly in the Finally clause.
You correctly use CompareExchange to test and set the m_synchPoint field when doing the initial check. You incorrectly use direct assignment to reset the value to 0 at the end of the method. You should use Interlocked.Exchange instead to reset the value to 0. As a side note, you should also change m_synchPoint to an instance field -- it should not be static.
Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,200));
t.Start();
I start a thread named 't' inside the 'Form1_Load' function. I have added a button. When click on that button the thread 't' should stop executing and create a new thread with these parameters.
Monitor moni = new Monitor();
Thread t = new Thread(() => moni.CurrUsage(nics,950));
t.Start();
I know in the form_load event i can use the
t.Abort();
By making t a member of the form, you can reference it later on in the button-click event handler.
Graceful Abort.
Although t.Abort() gets the job done, you might be left with half-processed data in the thread t. You can catch the ThreadAbortException in thread t to gracefully end processing.
Beware of overlap.
The second problem is that your thread might not have aborted yet while your new thread has started already. You can prevent that by calling t.Join() after calling t.Abort().
Hope this helps.
Make Thread t a private member of your form.
public partial class MainForm : Form
{
private Thread t;
}
One way is to make Thread t a global variable (place outside of Form_Load). Then it can be accessed and modified from any method in that class.
To instantiate the thread, use t = new Thread(.....
Before aborting the thread, make sure it is not null.
You need to make the Thread object accessable in both places that you need to access it.
In this case, making it a private varaible would work.
e.g.
public class MyClass
{
private Thread MyThread
{
get;
set;
}
private void myfunc1()
{
MyThread = new Thread(() => moni.CurrUsage(nics,200));
MyThread.Start();
}
private void myfunc2()
{
MyThread.Abort();
// I really need to wait until this thread has stopped...
MyThread.Join();
}
}
Adding to the already given answers:
Note that .Join() will block your current (UI) thread, leaving your application unresponsive to the user.
Just as another take: avoid using .Abort() by using a flag in your Monitor class to exit the task you are doing if possible. You can then still wait for .Join(), but you have full control of the state in the background thread.
public class Monitor
{
private bool _cancel = false;
public void Cancel()
{
_cancel = true;
}
public void CurrUsage(Nics nics, int n)
{
_cancel = false;
// ...
while (!_cancel)
{
// do some stuff
}
}
}
in your Form
private Monitor _monitor { get; set; }
private Thread _t;
public void Button_Click(...)
{
_monitor.Cancel()
_t.Join() // will return as your background thread has finished cleanly
_t = new Thread(() => _monitor.CurrUsage(nics,950));
t.Start();
}
As others have pointed out, all you need in order to call Abort is a reference to the thread (just like any other object in .NET).
However
You should seriously consider rethinking this approach. In general, calling Abort is discouraged, as it does not give the target thread sufficient opportunity to reach a stopping point. While it's sometimes appropriate (or the only option), it's almost always a better idea to ask the target thread to stop (usually through a volatile bool rather than forcing it like this.
For example,
public class ThreadClass
{
private volatile bool stopRequested;
private Thread thread;
public void Start()
{
stopRequested = false;
thread = new Thread(ThreadMethod);
thread.Start();
}
public void Stop()
{
stopRequested = true;
if(!thread.Join(5000)) thread.Abort(); // forcefully abort if not
// completed within 5 seconds
}
private void ThreadMethod()
{
}
}
Your code then goes into ThreadMethod. Within the method, periodically check the value of stopRequested. If it's true, perform whatever cleanup is necessary (if any) and gracefully return out of the thread. If the content is a loop, the general practice is to place the check at the start of the loop (assuming that the loop is sufficiently tight) and exit early if the value is true. The exact placement is really dependent upon the code, but the general idea is that it should be checked often enough to make the thread exit fairly quickly after it gets set, regardless of when that happens.
I have a method that updates records from the database, and I wonder if this method really runs in my BackGroundWorker thread considering the following:
public partial class Form1 : Form
{
BackgroundWorker bg = new BackgroundWorker();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerAsync();
}
void bg_DoWork(object sender, DoWorkEventArgs e)
{
UpdateDatabaseRecords(); // <-- Does this method runs in my BackGroundWorker?
}
private void UpdateDatabaseRecords()
{
SqlConnection conn = new SqlConnection();
// etc...
}
}
Is there a difference if I coded the update stuffs directly inside the bg_DoWork method?
Something like:
void bg_DoWork(object sender, DoWorkEventArgs e)
{
SqlConnection conn = new SqlConnection();
// etc...
// do the update codes here instead of doing
// it by calling another method.
}
Yes it is executing on a separate thread. No there wouldn't be a difference thread wise if you put it directly in that method.
Functions run in the thread that calls them, due to how function calls are implemented. So, since your background worker is calling the bg_DoWork function, it will be running in the worker's thread.
Because the code snippet appears small, there probably won't be a significant difference in calling another function. If you're just doing that little bit of work, then you can have it all in one function. If you start to increase the complexity of what the worker does, then you may want to start splitting it into many functions.
Yes it runs in a separate thread (background). The only difference is that you don't have access to the DoWorkEventArgs parameter, but you can pass it to your method.
No, there is no difference. Invoking a method creates a new stack-frame for the method call, pushes it onto the call-stack for the current thread, and then transfers control to it. It's also possible that the method may be inlined by the JIT compiler, so you may not see any difference in the disassembly between your 'manually inlined' version and your current version.
Btw, here's the code for BackgroundWorker.RunAsync from reflector:
public void RunWorkerAsync()
{
this.RunWorkerAsync(null);
}
public void RunWorkerAsync(object argument)
{
if (this.isRunning)
{
throw new InvalidOperationException(SR.GetString("BackgroundWorker_WorkerAlreadyRunning"));
}
this.isRunning = true;
this.cancellationPending = false;
this.asyncOperation = AsyncOperationManager.CreateOperation(null);
// the important bit
this.threadStart.BeginInvoke(argument, null, null);
}
As you can see, your code will run in the context of a WorkerThreadStartDelegate.BeginInvoke. This should mean that one of the thread-pool threads will pick it up, which you can verify by testing the value of Thread.CurrentThread.IsThreadPoolThread inside the bg_DoWork method.
I don't think so!
wrapping it in a method don't make it work in different thread, i think all of your code inside bg_DoWork will work on background worker (including all code on UpdateDatabaseRecords method).
there is a ThreadSynchronizationContext class where you can post your method to work on different thread context.
you can test your code on visual studio by put a break point inside bg_DoWork method and UpdateDatabaseRecords method. check it out from "Thread Window" from menu "Debug -> Windows-> Thread" investigate it weather it is work on main thread or worker thread.