简体   繁体   中英

C# Threading issue & best practices

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.

  1. The code works fine but i'm not sure if this the best solution
  2. 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 ?
  3. 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 ?
  4. 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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM