Vladica Jovanovski
Vladica Jovanovski

Reputation: 31

Call same method from different threads

For example we have 5 running threads. Each of them call the same method. When the methods is called, it will run on the current thread? That means that the same method will run separately on the different threads in the (relatively) same time?

Example:

public string GetHhmlCode(string url)
{
// ... Some code here
return html;
}

If we call this method from different threads with different parameter in the same time, the result will be return to appropriate thread which means that the code runs separately on different threads?

Upvotes: 3

Views: 9795

Answers (2)

Kiril
Kiril

Reputation: 40345

The short answer is to the first question is: Yes! The method will be executed by multiple threads concurrently.

The answer to the second question is: Yes (with reservations)! If you enter from a given thread context, then the method will return to the same thread context and all the treads will generally behave as if the other thread doesn't exist. However, this will quickly change if the threads have to read and/or write on the same variable. Consider this situation:

class HttpClient
{
    private volatile bool _httpClientConnected;
    //.. initialize in constructor

    public string GetHtmlCode(string url)
    {
        string html = string.Empty;
        if(_httpClientConnected)
        {
            html = FetchPage(url);
        }
        return html;
    }

    public void Connect()
    {
        _httpClientConnected = true;
        ConnectClient();
    }

    public void Disconnect()
    {
        _httpClientConnected = false;
        DisconnectClient();
    }
}

Suppose it is required that the client is connected for a page to be successfully fetched, then consider this order of execution:

Thread 1: calls GetHtmlCode
Thread 1: initialize local html variable
Thread 3: calls Disconnect()
Therad 2: calls GetHtmlCode
Thread 2: initialize local html variable
Thread 1: evaluate _httpClientConnected flag
Thread 3: sets _httpClientConnected to false
Therad 3: calls DisconnectClient() and successfully disconnects
THread 3: exits the Disconnect() method.
Thread 1: calls FetchPage()
Therad 2: evaluates _httpClientConnected flag
Thread 2: returns empty html string
Therad 1: catches an exception because it attempted to fetch a page when the client was disconnected

Thread 2 exited correctly, but Thread 1 possibly threw an exception and it may cause other problems in your code. Note that read/writing to the flag itself will be safe (i.e. those operations are atomic and visible to all threads due to the flag being labeled as volatile), however there is a race condition because the flag can be set AFTER a thread has already evaluated it. In this case there are a couple of ways to guard against the problem:

  1. Use a synchronization block (something like lock(syncObject){...})
  2. Create a separate http client for each thread (probably more efficient and it avoids synchronization).

Now let's look at another example:

public string GetHtmlCode(string url)
{
    string html = string.Empty;
    string schema = GetSchema(url);
    if(schema.Equals("http://"))
    {
        // get the html code
    }
    return html;
}

Suppose the following happens:

Thread 1: calls GetHtmlCode("http://www.abc.com/");
Thread 1: html is assigned an empty string
Thread 2: calls GetHtmlCode("ftp://www.xyz.com/");
Thread 2: html is assigned an empty string
Therad 1: assigns it's schema to the schema variable
Thread 2: assigns it's schema to the schema varaible
Thread 2: evaluates schema.Equals("http://")
Thread 1: evaluates schema.Equals("http://")
Thread 1: fetches html code
Therad 2: returns html
Therad 1: returns html

In this case both threads entered the method with different parameters and only Thread 1 entered with a parameter that could allow it to fetch a page, but Thread 2 did not interfere with Thread 1. The reason why this happens is because the threads don't share any common variables. A separate instance of the url parameter is passed in and each thread also gets its own local instance of schema (i.e. the schema is not shared because it only exists in the context of the calling thread).

Upvotes: 8

Chamika Sandamal
Chamika Sandamal

Reputation: 24302

mark this method as static and don't refer external variables inside this method. then it will work fine.

Upvotes: 2

Related Questions