In our application we used Threads and Delegate to get the best performance. In order to gate our operations we use the System.Timers.Timer class.
When the application start , after 1 hour the task manager shows that the number of handles increased and cpu usage increases as well.
What can we do to dispose objects of Thread and delegate?
below code can help you to check this task.
public partial class Form1 : Form
{
System.Timers.Timer MainTimer;
public Form1()
{
InitializeComponent();
MainTimer = new System.Timers.Timer();
MainTimer.Elapsed+=new System.Timers.ElapsedEventHandler(MainTimer_Elapsed);
}
Thread MainThread;
private void button1_Click(object sender, EventArgs e)
{
MainTimer.Interval = 10;
MainTimer.Start();
}
void MainTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
MainThread = new Thread(new ThreadStart(DoStart));
MainThread.Start();
}
void DoStart()
{
PrintInfo();
}
delegate void PrintInfo_Delegate();
void PrintInfo()
{
if (textBox1.InvokeRequired)
{
Invoke(new PrintInfo_Delegate(PrintInfo));
}
else
{
textBox1.Text += "Test\r\n";
}
}
}
Apologies if I'm misparsing something, but it looks like once the button is clicked, you're then starting a new thread (in MainTimer_Elapsed) every 10 milliseconds? Without knowing more about the context / versions, it's hard to give specific advice on an alternative (async/await, TPL, etc), but off-hand it seems like anything creating new threads (especially non-background threads) like that is doing so unnessarily?
For processing non-UI work, perhaps use ThreadPool.QueueUserWorkItem instead of creating your own? For UI work, maybe use BackgroundWorker? If you're exhausting the thread pool, you could also consider setting things like max thread count, but using TPL and avoiding the use/creation/management of threads would be better/simpler IMHO if you're able to target .Net 4.x
Related
I try to experiment with Thread.Sleep(). I created basic Windows Forms application with one button.
private void button1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(DoStuff);
thread1.Start();
for (int i = 0; i < 100000; i++)
{
Thread.Sleep(500);
button1.Text +=".";
}
}
public void DoStuff()
{
//DoStuff
}
When I click my button the DoStuff method works fine, but the GUI freezes and nothing happens. Can someone explain me why?
Thread.Sleep just sleeps the current thread (i.e. stops it from doing anything, such as redrawing, processing clicks etc), which in your case is the UI thread. If you put the Sleep in DoStuff you wouldn't experience the block as you'd be on a separate thread although you wouldn't be able to update button1. Depending on the version of .NET you're using consider using the Task Parallel Library, something like this:
private TaskScheduler _uiScheduler;
public Form1()
{
InitializeComponent();
_uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
}
private void button1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(DoStuff);
thread1.Start();
// Create a task on a new thread.
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 100000; i++)
{
Thread.Sleep(500);
// Create a new task on the UI thread to update the button
Task.Factory.StartNew(() =>
{ button1.Text += "."; }, CancellationToken.None, TaskCreationOptions.None, _uiScheduler);
}
});
}
To keep the UI active, you need for the main UI thread to service its message pump. It can only do that when it is not handling UI events. In your case the function
private void button1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(DoStuff);
thread1.Start();
for (int i = 0; i < 100000; i++)
{
Thread.Sleep(500);
button1.Text +=".";
}
}
does not return for around 100000*500 milliseconds. While this event handler is executing, the UI thread is busy. It is executing this event handler. As such it is not able to service the message pump. Hence your application's UI freezes.
For that you better use a Timer but if you want your current code to work you need to add Application.DoEvents(); after you update the button.Label += "."
If you're new to multithreading, I strongly encourage you to look at the Task Parallel Library (TPL). It simplifies threading, and gives you tools to help guarantee callback (continuation) threads occur on the UI thread.
The TPL is in the System.Threading.Tasks namespace.
Update: just seen your comment about .Net v2. TPL was introduced in .NET v3.5 or possibly as late as v4.
EDIT: After programming for a few more years, I now know how terrible of a practice this is. DO NOT DO ANYTHING I SUGGESTED BELOW. It's all crap. A more proper solution would be doing all of your intensive methods async all together. Regardless, don't do what I mention below.
All The methods above do work however, I do recommend just using an async void.
Sleep() just pauses the current thread for int amount of milliseconds, and if your whole program runs off of 1 thread, it'll pause the whole program. Don't quote me on this, I do believe that async creates a new thread specifically for that function.
Below I've included a better sleep function.
To call the function asleep(milliseconds),
replace "milliseconds" with how many milliseconds you wish to sleep for.
Function Code:
public async void asleep(int time){
await Task.Delay(time)
}
Re-arrange code as following
private void button1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(DoStuff);
thread1.Start();
}
public void DoStuff()
{
for (int i = 0; i < 100000; i++)
{
Thread.Sleep(500);
//Invoke goes here
}
}
Now you run your WORK in a separate thread and release your UI thread for usual work (Drawing related or other work)
NOTE - Now you will need Invoke methods to change Button text , else you will get warning for "Cross-thread operation not valid"
More on Invokes - How to update the GUI from another thread in C#?
I have wpf application, lets call it A-app. A-app runs asyncronic B-method with a background worker. That B-method is located at a different project, and it creates few threads for the B-method init part.
User can ask to run the B-method and can ask to cancel the run and restart.
The problem is that if it is cancelled in the init time, the background worker, which run the B-method is cancelled, but the threads are not.
Restarting creates more thread that cannot work at the same time as the threads from previous run, and it couse some bugs.
Threads method is mostly waiting.
How can I stop the B-method and also cancel the threads it created?
Is a different AppDomain could help in any way? (and than close the whole app domain?) If yes, that how should it be done?
Is there a better way?
More details:
The B-method runs tests on some devices (could be many). the init of the method is connecting to devices - i/o - so most time is spend on waiting (this is the reason we decided to make the connection init parallel).tring to connect to the same device from 2 different threads may cause problems.
I would suggest you don't create Threads at all but use the TaskScheduler and work with the Parallel Task Library:
http://msdn.microsoft.com/en-us/library/dd997402%28v=vs.110%29.aspx
The TaskScheduler himself is a wrapper for the ThreadPool, which handles the Threads. It even does stuf like WorkStealing, Task Inling etc.
At best you start here: http://msdn.microsoft.com/en-us/library/dd997402%28v=vs.110%29.aspx
Another approach is to start Tasks with a CancalletionToken, which enables you to cancel Tasks. See here: http://msdn.microsoft.com/en-us/library/dd537607%28v=vs.110%29.aspx
Edit: Okey, no TPL, Blocking Threads. This leaves basically only the Thread.Abort.
This is messy, but there is no perfect world, so think about the Form as Application A, and ClassB is Application B:
public partial class MainWindow : Window
{
Thread _threadA;
Thread _threadB;
Thread _threadC;
ClassB b1 = new ClassB();
ClassB b2 = new ClassB();
ClassB b3 = new ClassB();
public MainWindow()
{
InitializeComponent();
_threadA = new Thread(() => b1.DoSomeWork("A"));
_threadB = new Thread(() => b2.DoSomeWork("B"));
_threadC = new Thread(() => b3.DoSomeWork("C"));
}
private void btnStartWork_Click(object sender, RoutedEventArgs e)
{
_threadA.Start();
_threadB.Start();
_threadC.Start();
}
private void btnStopThreadA_Click(object sender, RoutedEventArgs e)
{
AbortThreadA();
}
private void btnStopThreadB_Click(object sender, RoutedEventArgs e)
{
AbortThreadB();
}
private void btnStopThreadC_Click(object sender, RoutedEventArgs e)
{
AbortThreadC();
}
private void AbortThreadA()
{
_threadA.Abort();
}
private void AbortThreadB()
{
_threadB.Abort();
}
private void AbortThreadC()
{
_threadC.Abort();
}
private void btnStopAll_Click(object sender, RoutedEventArgs e)
{
AbortThreadA();
AbortThreadB();
AbortThreadC();
}
}
class ClassB
{
public void DoSomeWork(string threadIdentifier)
{
try
{
string preWorkString = "Work work Okeydokey. Thread: " + threadIdentifier;
string postWorkString = "Job's Done. Thread: " + threadIdentifier;
while (true)
{
System.Diagnostics.Debug.WriteLine(preWorkString);
Thread.Sleep(5000);
System.Diagnostics.Debug.WriteLine(postWorkString);
}
}
catch (ThreadAbortException)
{
System.Diagnostics.Debug.WriteLine("Thread aborted. Thread: " + threadIdentifier);
Thread.ResetAbort();
}
}
}
ResetAbort is needed, otherwise the Error gets bubbled.
Is that a possible solution?
Do you own B-method (ie can you change it?)
I'm assuming B-method is not intrinsically cancellable, and you are just cancelling the background worker that calls it in module A?
B-method needs to be changed to either be cancellable, or re-entrant. By re-entrant I mean that it will allow multiple calls to itself, and will re-use any existing init sequence that is already in progress.
I have created a new Windows Forms Application with C# and .NET 4.0, and I have a function that must be called automatically every 60th of a second. My problem, is that I do not know where to call this function. .NET forms don't appear to have a built-in on-update event.
How would I go about getting this function called every 60th of a second?
Sorry if it is a beginner question.
You could set up a Timer to invoke a callback every 16 ms (which is 1/60 sec).
Important point as mentioned by #spender: If you are requiring very precise timing on this, eg exactly every 1/60 sec precision, you will not be satisfied with this solution. Windows does not natively do high-resolution timing in that vein very well. Props to #spender for the mention.
Here's a sample class with a rough outline of how it might look in a plain vanilla class, so you'd need to adapt it to your form:
You might also want to call this on a background thread, but if you're new to WinForms, we'll start in small chunks. Let's try the timer first, then go from there.
class Demo{
System.Timers.Timer myTimer;
void InitializeTimer(){
myTimer = new Timer(16); // elaps every 1/60 sec , appx 16 ms.
myTimer.ElapsedEventHandler+=new ElapsedEventHandler(myTimerEventHandler); //define a handler
myTimer.Enabled=true; //enable the timer.
}
void myTimerEventHandler(object sender, ElapsedEventArgs e){
// do your thing here
}
}
EDIT: Extra demo code for background thread creation and Invoked-based GUI update
As noted in my comment below, this is not as polished as I would like it, but I think it illustrates the salient points. It defines a BackgroundWorker thread to move the thread invocations to the background; the thread callback checks for the need to call Invoke, and calls right back to itself across a delegate invocation to allow for the custom form update in the "else" block of the "if (InvokeRequired)" statement. In a nutshell, a background thread starts, and starts a timer; when the timer elapses, it calls the updater on the background thread, which checks to see if Invoke must be called, and if it is, performs the thread context switch back to the GUI thread through the recall to the method, which then performs the GUI update. Put your custom update code in that "else" block. I hope this helps!!!
public partial class Form1 : Form
{
delegate void FormUpdateDelegate(object sender, ElapsedEventArgs e);
public BackgroundWorker backgroundThread;
System.Timers.Timer foo;
Random colorgen = new Random();
public Form1()
{
InitializeComponent();
backgroundThread = new BackgroundWorker();
backgroundThread.DoWork+=new DoWorkEventHandler(backgroundThread_DoWork);
backgroundThread.RunWorkerAsync();
}
public void formUpdater(object sender, ElapsedEventArgs e)
{
if (InvokeRequired)
{
FormUpdateDelegate d = new FormUpdateDelegate(formUpdater);
Invoke(d, new object[] { sender, e });
}
else
{
// Do your form update here
this.label1.ForeColor = Color.FromArgb(colorgen.Next());
}
}
public void backgroundThread_DoWork(object sender, DoWorkEventArgs e)
{
foo = new System.Timers.Timer(16);
foo.Elapsed += new ElapsedEventHandler(formUpdater);
foo.Start();
}
}
I just setup this in a console application, and it runs fine every second:
var timer = new System.Timers.Timer(1000);
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(delegate(object sender, ElapsedEventArgs eventArgs)
{
Console.WriteLine("Elapsed");
});
It is a bad practice to hope on system timers when you need precision at least 20 times per second.
I would recommend to use cycles like
Timespan timePerFrame = Timespan.FromMilliseconds(16);
while (_isRunning)
{
Stopwatch timer = Stopwatch.StartNew()
// Action.
while (timer.ElapsedMilliseconds < timePerFrame) { /* Nothing? */ }
}
That will give you the full precision, if your system supports high-precision stopwatch. (.IsHighResolution field).
I have a XAML application that serves as the UI for an automation. The entire automation can take anywhere from 20-30 hours to fully execute so I created a Task class object that essentially wraps Thread methods (Start/Stop/Reset).
However, when I run the automation method under the Task object, the XAML UI is busy and I cannot interact with the other controls, including the Pause button which toggles the Thread.Set() flag.
There is another post
Prevent UI from freezing without additional threads
where someone recommended the BackgroundWorker class this MSDN article mentions it is a bad idea to use this when if it manipulates objects in the UI, which mine does for purposes of displaying status counts:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Any idea around this?
private void OnButtonStartAutomationClick(object sender, RoutedEventArgs e)
{
btnPauseAutomation.IsEnabled = true;
Automation.Task AutomationThread = new Automation.Task(RunFullAutomation);
}
private void RunFullAutomation()
{
// do stuff that can take 20+ hours
// threaded so I can utilize a pause button (block)
}
class Task
{
private ManualResetEvent _shutdownFlag = new ManualResetEvent(false);
private ManualResetEvent _pauseFlag = new ManualResetEvent(true);
private Thread _thread;
private readonly Action _action;
public Task(Action action)
{
_action = action;
}
public void Start()
{
ThreadStart ts = new ThreadStart(DoDelegatedMethod);
_thread = new Thread(ts);
_thread.Start();
_thread.Priority = ThreadPriority.Lowest;
}
public void Resume()
{
_pauseFlag.Set();
}
public void Stop()
{
_shutdownFlag.Set();
_pauseFlag.Set();
_thread.Join();
}
private void DoDelegatedMethod()
{
do
{
_action();
}
while (!_shutdownFlag.WaitOne(0));
}
}
where someone recommended the BackgroundWorker class this MSDN article mentions it is a bad idea to use this when if it manipulates objects in the UI, which mine does for purposes of displaying status counts
BackgroundWorker is actually ideal for this, as it was designed for this type of scenario. The warning is that you shouldn't change UI elements inside of DoWork, but rather via ReportProgress and the ProgressChanged event.
The reason the warning exists is "DoWork" is executed on a background thread. If you set a UI element value from there, you'll get a cross threading exception. However, ReportProgress/ProgressChanged automatically marshals the call back into the proper SynchronizationContext for you.
Take a look at the Dispatcher object in WPF. You can, and should in your scenario, run the long running tasks on a background thread and the BackgroundWorker is a good way to do it. When you need to update the UI you need to verify access to the UI thread and if you don't have it use the dispatcher to invoke an update method on the UI thread.
There are two possible causes here: first, that the blocking task is blocking the UI thread rather than running on a background thread, and second, that the background thread is starving the UI thread so that it never gets the chance to respond to input. You need to find out which of these is the case. A crude way to do this is, in your Click handler, Debug.WriteLine the current thread ID (Thread.CurrentThread.ManagedThreadId), and do the same in the RunFullAutomation callback.
If these print the same number, then you have the first problem. Reed and TheZenker have provided solutions to this.
If these print different numbers, then you are already on a worker thread, and you have the second problem. (BackgroundWorker may get you to the worker thread more elegantly, and will help with updating the UI, but it won't stop starvation.) In this case the simplest fix is probably to set _thread.Priority = ThreadPriority.BelowNormal; before starting the worker thread.
By the way, your code never appears to actually call AutomationThread.Start, which means the RunFullAutomation callback isn't even executed. Is this just a typo?
I'd advise against rolling out your own Task class given that .NET 4 has full support for running tasks asynchronously in the background using the Task Parallel Library
That said,you can do what Reed suggests and use a BackgroundWorker which is ideal or if you prefer more control over the nature of how the task si executing, you could use the Task class from System.Threading.Tasks and implement something like so:
public partial class MainWindow : Window
{
CancellationTokenSource source = new CancellationTokenSource();
SynchronizationContext context = SynchronizationContext.Current;
Task task;
public MainWindow()
{
InitializeComponent();
}
private void DoWork()
{
for (int i = 0; i <= 100; i++)
{
Thread.Sleep(500); //simulate long running task
if (source.IsCancellationRequested)
{
context.Send((_) => labelPrg.Content = "Cancelled!!!", null);
break;
}
context.Send((_) => labelPrg.Content = prg.Value = prg.Value + 1, null);
}
}
private void Start_Click(object sender, RoutedEventArgs e)
{
task = Task.Factory.StartNew(DoWork, source.Token);
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
source.Cancel();
}
}
In DoWork() you use the WPF SynchronizationContext and post messages to update the UI wiget you need.
The example has a progress bar and a label control that is updated on each iteration of the for loop.Cancellation is supported using CancellationTokenSource which is checked in each iteration.
Hope this helps.
In this code, when button1 is clicked twice, it creates 2 separate threads. On one click, it creates a new thread on the heap and field t1 points to the new thread on the heap. When I click button2, it aborts the last thread (which t1 refers to).
How do I abort the other thread?
Thread t1;
ThreadStart ts1;
private void button1_Click(object sender, EventArgs e)
{
ts1 = new ThreadStart(myfunc);
t1 = new Thread(ts1);
t1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
t1.Abort();
}
Well, the OO answer would be to hold a list of threads as a field.
private readonly List<Thread> threads = new List<Thread>();
And to then add the newly constructed thread to the list in the first handler.
var thread = new Thread(myfunc);
thread.Start();
threads.Add(thread);
Then you could iterate through each thread in the second handler, aborting each of them in turn.
foreach(var thread in threads)
thread.Abort();
But I think the most important point here is that there is almost never a good reason to call Thread.Abort.
From the MSDN page:
When a thread calls Abort on itself,
the effect is similar to throwing an
exception; the ThreadAbortException
happens immediately, and the result is
predictable. However, if one thread
calls Abort on another thread, the
abort interrupts whatever code is
running. There is also a chance that a
static constructor could be aborted.
In rare cases, this might prevent
instances of that class from being
created in that application domain. In
the .NET Framework versions 1.0 and
1.1, there is a chance the thread could abort while a finally block is
running, in which case the finally
block is aborted.
The thread that calls Abort might
block if the thread that is being
aborted is in a protected region of
code, such as a catch block, finally
block, or constrained execution
region. If the thread that calls Abort
holds a lock that the aborted thread
requires, a deadlock can occur.
You would be much better off using some form of signalling, such as setting a ManualResetEvent that each thread will poll at perioidic intervals. Alternatively, you could use the BackgroundWorker class that has some support for task-cancellation (call CancelAsync on it, and get the worker threads to test CancellationPending periodically). If you are on .NET 4.0, you can also use the TPL.
I would recommend you to take a look at the built in synchronization primitives such as ManualResetEvent and WaitHandle. You can ask a thread if it's running or not by trying to join the thread with Thread.Join. Aborting a thread should only be done as a last resort if the thread is unresponsive.
Here is an modified example of your code that shows how you can prevent the thread from be restarted before it's been stopped properly.
public partial class MainForm : Form
{
private Thread t1;
private ThreadStart ts1;
private ManualResetEvent t1resetEvent;
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Got a thread?
if (t1 != null) {
if (!t1.Join(0)) {
// The thread seems to be running.
// You have to stop the thread first.
return;
}
}
t1resetEvent = new ManualResetEvent(false);
ts1 = new ThreadStart(MyFunc);
t1 = new Thread(ts1);
t1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
// Got a thread?
if (t1 != null)
{
// Set the reset event so the thread
// knows it's time to stop.
t1resetEvent.Set();
// Give the thread four seconds to stop.
if (!t1.Join(4000)) {
// It did not stop, so abort it.
t1.Abort();
}
}
}
private void MyFunc()
{
// Long running operation...
while (true)
{
// Do someone want us to exit?
if (t1resetEvent.WaitOne(0)) {
return;
}
}
}
}
The others have given the long versions of the answer, however the obvious simple solution is to simply skip recreating the thread object:
public partial class Form1 : Form
{
Thread thread1;
ThreadStart threadStart1;
public Form1()
{
InitializeComponent();
threadStart1 = new ThreadStart(threadTarget);
thread1 = new Thread(threadStart1);
thread1.Name = "Button1 thread";
}
private void button1_Click(object sender, EventArgs e)
{
thread1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
thread1.Abort();
}
private void threadTarget()
{
Console.WriteLine(Thread.CurrentThread.Name);
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i);
Thread.Sleep(500);
}
}
}
However, I would consider reading up on Threading in .NET using one these guides (I'd recommend Joseph Albahari's guide on aborting - the author of C# in a nutshell) rather than use this method, particularly if you're performing IO or database operations which can leave the objects in unexpected states.
Also, have in mind that calling Abort on a Thread is evil. You should stop the thread with a boolean condition or something like that.
Check this:
http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation