Iterating the assignment of a variable's name - c#

So this is something I've always wondered..
Say I want 10 threads called t1 t2 t3 etc... But I don't want to write
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
Thread t3 = new Thread(run);
...
Rather something like this: (pseudo-code)
for(int i = 0; i <= 10; i++){
Thread t + i = new Thread(run);
}
Is there any way to do this?
Thanks in advance.
Edit: Okay, so this is basically what I wanted to do:
static void Main(string[] args)
{
int n = 0;
Program p = new Program();
List<Thread> threads = new List<Thread>();
for(int i = 0; i <= 10; i++)
{
threads.Add(new Thread(p.run));
}
foreach(Thread t in threads)
{
n++;
t.Name = "Thread " + n;
t.IsBackground = true;
t.Start();
}
Console.ReadKey(false);
}
Thanks all!

No, that's not possible. Why not just this?
for(int i = 0; i <= 10; i++){
new Thread(run);
}
If you really want to keep references to each thread, you can store them in a list.

Related

I can not recreate thread competing effect

I read, in many many articles, that multiple threads will "compete" for the same resource and try to recreate it with the following code:
static void Main(string[] args)
{
List<int> list = new List<int>();
Thread t1 = new Thread(thread1);
t1.IsBackground = true;
t1.Start();
Thread t2 = new Thread(thread2);
t2.IsBackground = true;
t2.Start();
Thread.Sleep(3000);
foreach(int i in list)
{
Console.WriteLine(i);
}
Console.ReadLine();
void thread1()
{
for (int i = 0; i < 10000; i++)
{
list.Add(i);
}
}
void thread2()
{
for (int i = 10000; i < 20000; i++)
{
list.Add(i);
}
}
}
But the result is still very "nice and neat" in order (from 0 to 19999), what did I do wrong?

variable safety in unity thread

As far as I know, the variable in thread should be not safe if not locked. But I tried it on Unity, and found it different.
I try the code below:
void Awake () {
Thread thread = new Thread(new ThreadStart (demo));
thread.Start ();
for (int i = 0; i < 5000; i++) {
count = count + 1;
}
}
void demo() {
for (int i = 0; i < 5000; i++) {
count = count + 1;
}
}
And I try to Debug.Log(count), and every times I try it that is 10000. But it should be a number which is less than 10000 because of not thread safety, shouldn't it? So can anyone tell me why?
Here's an Minimal, Complete, and Verifiable example of your code:
void Main()
{
Awake();
Console.WriteLine(count);
}
private int count = 0;
public void Awake()
{
Thread thread = new Thread(new ThreadStart(demo));
thread.Start();
for (int i = 0; i < 5000; i++)
{
count = count + 1;
}
thread.Join();
}
public void demo()
{
for (int i = 0; i < 5000; i++)
{
count = count + 1;
}
}
If you run that you get 10000 out. This is because by the time the thread has started the .Awake() method has finished its loop and thus no conflict occurs.
Try changing the loops to for (int i = 0; i < 50000; i++) then the result I got for one run is 89922. It changes each time, but sometimes I still get 100000.
The thread need some time to schedule to start. The main thread might finish the increments before the other thread start. Try to use a large value like 50000000.

How to get and print how many times a loop spins in a thread before it gets switched to other threads?

Instead of printing o and -, I want to print the number of o and - on the console. However, I have no idea how to get how many times a loop spins in a thread before it gets switched to other threads.
If there are events something likes OnLeaving and OnEntering on a thread, I can get the number of spins in the given time slice. Unfortunately, I have no such events.
class Program
{
public const int N = 1000;
static void Main(string[] args)
{
ThreadStart ts = DoWork;
Thread t = new Thread(ts);
t.Start();
for (int x = 0; x < N; x++)
{
Console.Write('o');
}
t.Join();
}
private static void DoWork()
{
for (int x = 0; x < N; x++)
{
Console.Write('-');
}
}
}
Could you show me how to do this scenario?
To reiterate: AbhayDixit's comment gives you a cycle counter. You just need to add a locking mechanism and reset the counters after a context switch.
I have modified your code to include a cycle counter. Note that I have increased N significantly. Otherwise, one thread will just run through its 1000 iterations at once - because you no longer have a Write() instruction to slow it down.
class Program
{
public const int N = 1000000;
private static object _l = new object();
private static int _i = 0;
private static int _j = 0;
static void Main(string[] args)
{
ThreadStart ts = DoWork;
Thread t = new Thread(ts);
t.Start();
for (int x = 0; x < N; x++)
{
lock (_l)
{
// j-thread has run?
if (_j > 0)
{
// print and reset j
Console.Write("j{0} ", _j);
_j = 0;
}
_i++;
}
}
t.Join();
// print remaining cycles
// one of the threads will have run after the other has finished and
// hence not been printed and reset.
if (_i > 0)
Console.Write("i{0} ", _i);
if (_j > 0)
Console.Write("j{0} ", _j);
Console.ReadKey();
}
private static void DoWork()
{
for (int x = 0; x < N; x++)
{
lock (_l)
{
// i-thread has run?
if (_i > 0)
{
// print and reset i
Console.Write("i{0} ", _i);
_i = 0;
}
_j++;
}
}
}
}

An unhandled exception of type 'System.StackOverflowException' in code

I have been getter the error above at random times. One time the bot passess the point of collectiong 200 k links without the above than at some point it gives the error at 80 k another at 150 k etc. So it is random.
Searching the error i read that it is dues to some threads stuck in something and repeatedly calling itself causing this.
So i went through all my code but i do not see any while or other loops than can be infinite loops other than the main top one to start the threads ?
Here is the main code:First i start the threads :
for (int j = 0; j < 10; j++)
{
Console.Write("STARTING THREADS " + j);
Thread thread = new Thread(() => startPosting2());
thread.IsBackground = true;
thread.Start();
Random rnd = new Random();
int x = 0;
x = rnd.Next(1, 10);
System.Threading.Thread.Sleep(1000 * x);
}
Than the scraping :
static int rowCounter = -1;
int totalRows = 0;
static private Object thisLock = new Object();
public void startPosting2()
{
while (rowCounter < urlList.Count)
{
try
{
//List<Thread> threads = new List<Thread>();
int tmprowCounter = 0;
lock (thisLock)
{
rowCounter = rowCounter + 1;
tmprowCounter = rowCounter;
}
string url = urlList[tmprowCounter].ToString();
scrapsomething(url);
}
catch(Exception ex)
{}
}
The above is the only while loop but it get more link as it goes to total rows can be 100 when it enter the loop and can be 100k and its still in the loop as until it keeps getting links inside it keep adding to the urlList . Can this be the cause, And is it bad coding?
UPDATE
What if i change the above code to as follows :
static int rowCounter = -1;
int totalRows = 0;
static private Object thisLock = new Object();
public void startPosting2()
{
while (rowCounter < urlList.Count)
{
try
{
//List<Thread> threads = new List<Thread>();
int tmprowCounter = 0;
lock (thisLock)
{
rowCounter = rowCounter + 1;
tmprowCounter = rowCounter;
}
string url = urlList[tmprowCounter].ToString();
Thread t = new Thread(() => scrapeSiteCollectLinks(url));
t.Start();
t.Join(60000);
}
catch(Exception ex)
{}
}
Will this help ! As if any thing is getting stuck it has to quit after 60 seconds time out ? Is this logic correct?

Wait for threads to complete

private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 15; i++)
{
Thread nova = new Thread(Method);
nova.Start();
}
listBox1.Items.Add("Some text");
}
private void Method()
{
for (int i = 0; i < 15; i++)
{
Console.WriteLine(i);
}
}
This code does write: Some text and then numbers 111222333.....
I would like that it writes 111122223333.... and then on the end Some text.
is it possible to do that with threads (parent thread wait for child threads)? or do i have to use something else?
You need to keep track of all the threads, and use Thread.Join on each one. This waits until the specified thread terminates, and then continues executing. Like this:
var threads = new List<Thread>();
for (int i = 0; i < 15; i++)
{
Thread nova = new Thread(Method);
nova.Start();
threads.Add(nova);
}
foreach (var thread in threads)
thread.Join();
listBox1.Items.Add("Some text");
I suggest to use TPL to get this done. You won't need to spawn so many threads. By default TPL will use thread pool for that:
using System;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private const int TaskCount = 15;
static void Main(string[] args)
{
var tasks = new Task[TaskCount];
for (var index = 0; index < TaskCount; index++)
{
tasks[index] = Task.Factory.StartNew(Method);
}
Task.WaitAll(tasks);
Console.WriteLine("Some text");
}
private static void Method()
{
for (int i = 0; i < 15; i++)
{
Console.WriteLine(i);
}
}
}
}
You could have two threads, the 2nd one waiting on a signal to fire from the first.
private void Foo()
{
var signals = new List<ManualResetEvent>();
for (int i = 0; i < 15; i++)
{
var signal = new ManualResetEvent(false);
signals.Add(signal);
var thread = new Thread(() => { Method(); signal.Set(); });
thread.Start();
}
var completionTask = new Thread(() =>
{
WaitHandle.WaitAll(signals.ToArray());
CompletionWork();
});
completionTask.Start();
}
private void Method()
{
}
private void CompletionWork()
{
}
The better solution now with .Net 4.0 (and later) is to use Tasks, and invoke a method using ContinueWith
private void Foo()
{
var childThreads = new List<Task>();
for (int i = 0; i < 15; i++)
{
var task = new Task(Method);
task.Start();
childThreads.Add(task);
}
var completionTask = new Task(() =>
{
Task.WaitAll(childThreads.ToArray());
}).ContinueWith(t => CompletionWork());
}
private void Method()
{
}
private void CompletionWork()
{
}
The join answers also work, but require the containing thread to block. If you don't want the GUI to block, Spawn an additional thread around the 1st.
You can use thread.join to wait for threads to end. See http://www.dotnetperls.com/thread-join for an page on how to use it.

Categories