从不同的线程调用相同的方法

时间:2011-09-24 03:15:55

标签: c# multithreading methods call

例如,我们有5个正在运行的线程。他们每个人都使用相同的方法。调用方法时,它会在当前线程上运行吗?这意味着相同的方法将在(相对)相同的时间内在不同的线程上单独运行?

示例:

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

如果我们同时从具有不同参数的不同线程调用此方法,结果将返回到相应的线程,这意味着代码在不同的线程上单独运行?

2 个答案:

答案 0 :(得分:7)

简短的回答是第一个问题是:是的!该方法将由多个线程同时执行。

第二个问题的答案是:是(有预订)!如果从给定的线程上下文进入,则该方法将返回到相同的线程上下文,并且所有步骤通常表现得好像其他线程不存在一样。但是,如果线程必须读取和/或写入相同的变量,这将很快改变。考虑一下这种情况:

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();
    }
}

假设需要连接客户端才能成功获取页面,然后考虑这个执行顺序:

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

线程2正确退出,但是线程1可能引发异常,这可能会导致代码中出现其他问题。请注意,对标志本身的读/写将是安全的(即,由于标志被标记为易失性,这些操作是原子的并且对所有线程可见),但是存在竞争条件,因为可以在线程已经设置之后设置标志评估它。在这种情况下,有几种方法可以防止这个问题:

  1. 使用同步块(类似lock(syncObject){...}
  2. 为每个线程创建一个单独的http客户端(可能效率更高,避免同步)。
  3. 现在让我们看另一个例子:

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

    假设发生以下情况:

    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
    

    在这种情况下,两个线程都使用不同的参数进入方法,并且只输入了一个可以允许它获取页面的参数的线程1,但是线程2没有干扰线程1.发生这种情况的原因是因为线程不要共享任何常见变量。传入url参数的单独实例,每个线程也获得自己的本地模式实例(即模式不共享,因为它只存在于调用线程的上下文中。)

答案 1 :(得分:1)

将此方法标记为静态,并且不要在此方法中引用外部变量。然后它会正常工作。