I just wanted to ask a clarification about the program below:
foreach (Match match in MC)
{
string link = match.Groups["link"].ToString();
if (link.Contains("ebay.de/itm/"))
{
int endIndex = link.IndexOf("?pt");
link = link.Substring(0, endIndex);
if (link != lastLink)
{
getEanPerLink = delegate
{
getEan(link);
};
new Thread(getEanPerLink).Start();
}
lastLink = link;
}
}
It creates a lot of threads when the program loops. I just wanted to ask if those threads ends or exits itself. Or if not, how can I abort each of those threads created?
Each thread will end when the getEan method exits. If it does, then you don't have to do anything more, the thread and the Thread object will go away cleanly.
It's possible to abort threads, but it's not recommended because it throws an exception in the middle of whatever the thread is doing. The recommended way is to communicate to the thread that you want it to end, so that it can do that at a convenient place in the code.
Make them as background threads than thay will be closed when you close or abort the running thread.
My recommnedition do not use threads in this; way this is a bad way to use thread.
if you r using .net 4.5 use async await
if you r using .net 4 use Task
if you r using .net 3.5 use ThreadPool
if you r using .net 2 backgroundWorker
Greertings,
Bassam
Related
This is my 1st time using threading in an C# Application. Basically its an application which checks a bunch of web sites in a list whether its dead or alive.
Here is my 1st attempt to work with multi-threading
public void StartThread(string URL,int no)
{
Thread newThread = new Thread(() =>
{
BeginInvoke(new Action(() => richTextBox1.Text += "Thread " + no + " Running" + Environment.NewLine));
bool b = ping(URL);
if (b == true) { BeginInvoke(new Action(() => richTextBox2.Text += "Okay" + Environment.NewLine)); }
else
{ return; }
});
newThread.Start();
}
I'm using the above function to create new threads and each thread is created inside a loop.
foreach (string site in website) {
StartThread(site,i);
i++; // Counter }
Since i'm a beginner i have few questions.
The code works fine but i'm not sure if this the best solution
Sometimes threads run perfectly but sometimes Threads does not return any values from the method ping() which checks the host and returns true if its online using WebRequest. is it usual ?
If i ask the user to specify a no of threads that he needs to use , how can i equally distribute work among those threads ?
Is their an elegant way that i track the status of the thread, ( dead / alive ) ? i currently use rocess.GetCurrentProcess().Threads.Count;
spinning up a new thread for each request is inefficient ... you probably will want to have a fixed number of worker threads (so one can run on each core of the cpu)
have a look at the ConcurrentQueue<T> class, which will give you a thread safe first-in-first-out queue where you can enqueue your requests and let each worker thread dequeue a request, process it, and so on until the queue is empty ...
be aware that you may not call controls on your GUI from other threads than the main GUI thread ... have a look at the ISynchronizeInvoke Interface which can help you decide if an cross thread situation needs to be handled by invoking another thread
1) Your solution is OK. The Thread class has been partially superseded by the Task class, if you're writing new code, you can use that. There is also something completely new in .NET 4.5, called await .However, see 4).
2) Your ping method might simply be crashing if the website is dead. You can show us the code of that method.
4)Thread class is nice because you can easily check the thread state, as per your requirements, using the ThreadState property - just create a List<Thread> , put your threads in it, and then start them one by one.
3)If you want to load the number of threads from input and distribute the work evenly, put the tasks in a queue (you can use the ConcurrentQueue that has already been suggested) and have the threads load the URLs from the queue. Sample code:
you initialize everything
void initialize(){
ConcurrentQueue<string> queue = new ConcurrentQueue<string>();
foreach(string url in websites)
{
queue.Enqueue(url);
}
//and the threads
List<Thread> threads = new List<Thread>();
for (int i = 0; i < threadCountFromTheUser; i++)
{
threads.Add(new Thread(work));
}}
//work method
void work()
{
while (!queue.IsEmpty)
{
string url;
bool fetchedUrl = queue.TryDequeue(out url);
if (fetchedUrl)
ping(url);
}
}
and then run
foreach (Thread t in threads)
{
t.Start();
}
Code not tested
You should consider the .Net ThreadPool. However, it's generally unsuitable for threads that take more than about second to execute.
See also:
Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4
I have a function where I want to execute in a separate thread avoiding two threads to access the same resources. Also I want to make sure that if the thread is currently executing then stop that thread and start executing the new thread. This is what I have:
volatile int threadCount = 0; // use it to know the number of threads being executed
private void DoWork(string text, Action OncallbackDone)
{
threadCount++;
var t = new Thread(new ThreadStart(() =>
{
lock (_lock) // make sure that this code is only accessed by one thread
{
if (threadCount > 1) // if a new thread got in here return and let the last one execute
{
threadCount--;
return;
}
// do some work in here
Thread.Sleep(1000);
OncallbackDone();
threadCount--;
}
}));
t.Start();
}
if I fire that method 5 times then all the threads will be waiting for the lock until the lock is released. I want to make sure that I execute the last thread though. when the threads are waiting to be the owner of the lock how can I determine which will be the next one owning the lock. I want them to own the resource in the order that I created the threads...
EDIT
I am not creating this application with .net 4.0 . Sorry for not mentioning what I was trying to accomplish. I am creating an autocomplete control where I am filtering a lot of data. I don't want the main window to freeze eveytime I want to filter results. also I want to filter results as the user types. If the user types 5 letters at once I want to stop all threads and I will just be interested in the last one. because the lock blocks all the threads sometimes the last thread that I created may own the lock first.
I think you are overcomplicating this. If you are able to use 4.0, then just use the Task Parallel Library. With it, you can just set up a ContinueWith function so that threads that must happen in a certain order are done in the order you dictate. If this is NOT what you are looking for, then I actually would suggest that you not use threading, as this sounds like a synchronous action that you are trying to force into parallelism.
If you are just looking to cancel tasks: then here is a SO question on how to cancel TPL tasks. Why waste the resources if you are just going to dump them all except for the last one.
If you are not using 4.0, then you can accomplish the same thing with a Background Worker. It just takes more boilerplate code to accomplish the same thing :)
I agree with Justin in that you should use the .NET 4 Task Parallel Library. But if you want complete control you should not use the default Task Scheduler, which favors LIFO, but create your own Task Scheduler (http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.aspx) and implement the logic that you want to determine which task gets preference.
Using Threads directly is not recommended unless you have deep knowledge of .NET Threading. If you are on .NET 4.0; Tasks and TPL are preferred.
This is what I came up with after reading the links that you guys posted. I guess I needed a Queue therefore I implemented:
volatile int threadCount = 0;
private void GetPredicateAsync(string text, Action<object> DoneCallback)
{
threadCount++;
ThreadPool.QueueUserWorkItem((x) =>
{
lock (_lock)
{
if (threadCount > 1) // disable executing threads at same time
{
threadCount--;
return; // if a new thread is created exit.
// let the newer task do work!
}
// do work in here
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
threadCount--;
DoneCallback(Foo);
}));
}
},text);
}
well, i make a loop that makes a lot of threads, see:
foreach (DataGridViewRow dgvRow in dataGridView1.Rows)
{
Class h = new Class(dgvRow.Cells["name"].Value.ToString());
Thread trdmyClass = new Thread(h.SeeInfoAboutName);
trdmyClass.IsBackground = true;
trdmyClass.Start();
}
This is working fine, creating the threads that i need, but i want to stop all this threads (using Thread.Abort()), in one time when i click on a button for e.g.
How can i do this?
I wouldn't use Thread.Abort. It can have some very nasty consequences. What you should be doing is keeping track of the threads you create by putting them into a list. You can then use a ManualResetEvent class. The threads should check if the reset was raised or not periodically and if it has been set, they should cleanup and exit. I use the WaitOne method will a millisecond timeout and then check the return value to allow threads to run in a loop. If true is returned the signal is set and you can exit the loop or otherwise return from your thread. If you're using .Net 4, you can also use a CancelationToken as well.
http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx
http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.aspx
Read more about the issues with Thread.Abort here: http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx
EDIT: I use a ManualResetEvent as its thread safe and you could use it to syncronize the processing in the threads, for example if you're doing a producer / consumer pattern. A volatile boolean could be used as well. I recommend keeping the threads in a list in case you need to wait for them to complete, so you can Join on each one. This may or may not be applicable to your problem though. Its usually a good idea, especially if you're exiting, to Join all your threads to allow them to finish any cleanup they may be doing.
You really shouldn't use Thread.Abort(), it can be very dangerous. Instead, you should provide some way to signal to the threads that they are canceled. Each thread would then periodically check whether it's canceled and end if it was.
One way to do this would be to use CancellationToken, which does exactly that. The framework methods that support cancellation work with this type too.
Your code could then look something like this:
// field to keep CancellationTokenSource:
CancellationTokenSource m_cts;
// in your method:
m_cts = new CancellationTokenSource();
foreach (DataGridViewRow dgvRow in dataGridView1.Rows)
{
Class h = new Class(dgvRow.Cells["name"].Value.ToString());
Thread trdmyClass = new Thread(() => h.SeeInfoAboutName(m_cts.Token));
trdmyClass.IsBackground = true;
trdmyClass.Start();
}
//somewhere else, where you want to cancel the threads:
m_cts.Cancel();
// the SeeInfoAboutName() method
public void SeeInfoAboutName(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
// do some work
}
}
Keep all the threads in a List, and then loop through the list and stop them.
I am using the BackgroundWorker to do some heavy stuff in the background so that the UI does not become unresponsive.
But today I noticed that when I run my program, only one of the two CPUs is being used.
Is there any way to use all CPUs with the BackgroundWorker?
Here is my simplified code, just if you are curious!
private System.ComponentModel.BackgroundWorker bwPatchApplier;
this.bwPatchApplier.WorkerReportsProgress = true;
this.bwPatchApplier.DoWork += new System.ComponentModel.DoWorkEventHandler(this.bwPatchApplier_DoWork);
this.bwPatchApplier.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.bwPatchApplier_ProgressChanged);
this.bwPatchApplier.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.bwPatchApplier_RunWorkerCompleted);
private void bwPatchApplier_DoWork(object sender, DoWorkEventArgs e)
{
string pc1WorkflowName;
string pc2WorkflowName;
if (!GetWorkflowSettings(out pc1WorkflowName, out pc2WorkflowName)) return;
int progressPercentage = 0;
var weWorkspaces = (List<WEWorkspace>) e.Argument;
foreach (WEWorkspace weWorkspace in weWorkspaces)
{
using (var spSite = new SPSite(weWorkspace.SiteId))
{
foreach (SPWeb web in spSite.AllWebs)
{
using (SPWeb spWeb = spSite.OpenWeb(web.ID))
{
PrintHeader(spWeb.ID, spWeb.Title, spWeb.Url, bwPatchApplier);
try
{
for (int index = 0; index < spWeb.Lists.Count; index++)
{
SPList spList = spWeb.Lists[index];
if (spList.Hidden) continue;
string listName = spList.Title;
if (listName.Equals("PC1") || listName.Equals("PC2"))
{
#region STEP 1
// STEP 1: Remove Workflow
#endregion
#region STEP 2
// STEP 2: Add Events: Adding & Updating
#endregion
}
if ((uint) spList.BaseTemplate == 10135 || (uint) spList.BaseTemplate == 10134)
{
#region STEP 3
// STEP 3: Configure Custom AssignedToEmail Property
#endregion
#region STEP 4
if (enableAssignToEmail)
{
// STEP 4: Install AssignedTo events to Work lists
}
#endregion
}
#region STEP 5
// STEP 5 Install Notification Events
#endregion
#region STEP 6
// STEP 6 Install Report List Events
#endregion
progressPercentage += TotalSteps;
UpdatePercentage(progressPercentage, bwPatchApplier);
}
}
catch (Exception exception)
{
progressPercentage += TotalSteps;
UpdatePercentage(progressPercentage, bwPatchApplier);
}
}
}
}
}
PrintMessage(string.Empty, bwPatchApplier);
PrintMessage("*** Process Completed", bwPatchApplier);
UpdateStatus("Process Completed", bwPatchApplier);
}
Thanks a lot for looking into this :)
The BackgroundWorker does its work within a single background (ThreadPool) thread. As such, if it's computationally heavy, it'll use one CPU heavily. The UI thread is still running on the second, but is probably (like most user interface work) spending almost all of its time idle waiting for input (which is a good thing).
If you want to split your work up to use more than one CPU, you'll need to use some other techniques. This could be multiple BackgroundWorker components, each doing some work, or using the ThreadPool directly. Parallel programming has been simplified in .NET 4 via the TPL, which is likely a very good option. For details, you can see my series on the TPL or MSDN's page on the Task Parallel Library.
Each BackgroundWorker uses only a single thread to do the stuff you tell it to do. To take advantage of multiple cores, you would need multiple threads. That would mean either multiple BackgroundWorkers or spawning multiple threads from within your DoWork method.
The backgroundworker, by itself, only provides one additional thread of execution. It's purpose is to get things off the UI thread, and it's very good at that job. If you want more threads, you need to provide them yourself.
It would be tempting here to build a method that accepts an SPWeb argument, and just call Thread.Start() over and over for each object; then finish with Thread.Join() or WaitAll() to wait for them to finish at the end of the BackgroundWorker. However, this would be a bad idea because you'll lose efficiency as the operating system spends time performing context switches among all the threads.
Instead, you want to force your system to run in only a few threads, but at least two (in this case). A good rule of thumb is (2n - 1), where "n" is the number of processor cores you have... but there are all kinds of cases where you want to break this rule. You can implement this by using a ThreadPool, by iterating over your SPWeb objects and adding them to a queue that you keep pulling from, or other means such as the TPL.
The BackgroundWorker is running a new thread on the second CPU core, leaving the UI responsive.
If you're using .NET 4, look into using the Task Parallel Library, which could give you better results and utilize both cores.
The BackgroundWorker itself is only creating a single thread apart from your main UI to do work in - it's not trying to parallelize the operations within that work thread. If you want to spread your work across multiple work threads you should look into using the TPL. Bear in mind that not all tasks translate well to parallel execution, so if freeing the UI is your only goal this may already be the best you can do.
There are potential pitfalls to this, but you might get some mileage out of utilizing Parallel.ForEach:
Instead of
foreach (SPWeb web in spSite.AllWebs)
{
//Your loop code here
}
You could:
Parallel.Foreach(spSite.AllWebs, web =>
{
//Your loop code here
});
This basically creates a Task (from the Task API in .NET 4.0) from each item and schedules that work with the TaskPool, which will give you some of the parallelism you will need to take advantage of those cores.
You will have to fix the inevitable concurrency problems that might arise from this, but it's a good starting point. You are going to at least fix the fact that you are maintaining a shared state across threads (the progress counter). Here's some guidance on that: http://msdn.microsoft.com/en-us/library/dd997392.aspx
I have a thread:
void threadCode(object o)
{
doStuffHere(o); // Blocking call. Sometimes hangs.
}
and I'm calling it like this:
Thread t = new Thread(new ThreadStart(delegate()
{
threadCode(o);
}));
t.Start();
StopWatch sw = new StopWatch();
sw.Start();
while (t.IsAlive)
{
Application.DoEvents();
if (sw.EllapsedMilliseconds > myTimeout)
// Somehow kill t even though doStuffHere(o) is blocked (but hung)
}
I'm using the .NET Zip Library and calling ZipFile.CommitUpdate() which works most of the time, but sometimes just hangs. I don't know why, I can't see anything in the documentation which specifies why this is happening. A small file which should take no longer than 5 - 10 seconds will sometimes sit there for more then 5 minutes with no progress. I/O graphs in process explorer show that the process is not reading or writing, and there is no CPU usage. Basically, if this happens, I want to kill CommitUpdate() and try again once or twice before giving up.
Any idea how I can kill a thread stuck in a blocking call?
(Alternatively - those of you with experience with this zip library: do you know why it might be hanging with some files sometimes? I'm modifying the contents of .docx and .pptx (GZip) files. This would be an ideal solution.)
If you're going to terminate the hanging thread by using Thread.Abort(), make sure you handle ThreadAbortException in your thread code. The normal pattern is:
try {
// do work here
}
catch (ThreadAbortException) {
// allows your thread to gracefully terminate
Thread.ResetAbort();
}
catch {
// regular exception handling
}
If you don't follow the above pattern, then at best your threads will terminate ungracefully. At worst, you could run into a number of other problems.
You can call Thread.Abort to bloodily murder the thread.
The thread will not be able to clean up after itself (except for finally blocks); depending on exactly what it was doing at the time, it could seriously mess up your program.
DO NOT use Thread.Abort() to workaround a bug in a library you're using. (Or it could be a bug in your code).
Either get the original bug fixed, or move to a different library.
ps: You might want to try DotNetZip, in lieu of SharpZipLib.
Alternative to using a Stopwatch, you could do this:
Thread thread = new Thread(new ThreadStart(delegate()
{
threadCode(o);
}));
thread.Start();
thread.Join(myTimeout);
if(thread.IsAlive)
{
thread.Abort();
}
Use the Thread.Abort() method to kill a thread. See http://msdn.microsoft.com/en-us/library/aa332365(VS.71).aspx for more details.
As a last resort you could use Thread.Abort() to terminate the thread - don't expect any orderly shutdown.
I haven't done this myself, so I not sure about this, but does t.Abort(); do the trick?