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

C# 从不同线程调用相同的方法,c#,multithreading,methods,call,C#,Multithreading,Methods,Call,例如,我们有5个正在运行的线程。它们都调用相同的方法。调用这些方法时,它将在当前线程上运行?这意味着相同的方法将在(相对)相同的时间内在不同的线程上分别运行 例如: public string GetHhmlCode(string url) { // ... Some code here return html; } 如果我们同时从具有不同参数的不同线程调用此方法,结果将返回到相应的线程,这意味着代码在不同线程上分别运行 将此方法标记为静态,不要在该方法中引用外部变量。那么它就可以正常工作了。

例如,我们有5个正在运行的线程。它们都调用相同的方法。调用这些方法时,它将在当前线程上运行?这意味着相同的方法将在(相对)相同的时间内在不同的线程上分别运行

例如:

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

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

将此方法标记为静态,不要在该方法中引用外部变量。那么它就可以正常工作了。

第一个问题的简短答案是:是的!该方法将由多个线程并发执行

第二个问题的答案是:是(有保留)!如果您从给定的线程上下文输入,那么该方法将返回到相同的线程上下文,并且所有踏板的行为通常与其他线程不存在一样。但是,如果线程必须读取和/或写入同一个变量,这将很快发生变化。考虑这种情况:

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可能引发异常,并可能导致代码中出现其他问题。请注意,对标志本身的读/写操作是安全的(即,由于标志被标记为volatile,因此这些操作是原子的,对所有线程都可见),但是存在争用条件,因为可以在线程对标志进行求值之后设置标志。在这种情况下,有两种方法可以预防该问题:

  • 使用同步块(类似于
    锁(syncObject){…}
  • 为每个线程创建一个单独的http客户端(可能效率更高,而且可以避免同步)
  • 现在让我们看另一个例子:

    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
    参数的一个单独实例,每个线程还获取其自己的本地架构实例(即,架构不共享,因为它只存在于调用线程的上下文中)。

    该方法将在调用它的线程上运行。我建议编写一个线程教程:@BrokenGlass:请去掉.NET 1.1链接虽然这些通常都是好主意,但对于线程安全来说既不必要也不充分。是的-我当然会为每个线程使用单独的http客户端。如果引入竞态条件,并且必须实现lock()机制,我一直想知道这是否意味着所有线程都必须等到另一个线程完成后才能继续?如果是这样的话,如果您不得不等待,那么这种情况是否会违背并发线程的目的?我总是发现简单地将执行代码复制/粘贴到线程的DoWork()方法中更容易,尤其是当我必须将参数传递给该方法时。这样,它们就可以真正同时运行,并实现效率。对