Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用成员函数启动线程_C#_Multithreading_Delegates - Fatal编程技术网

C# 使用成员函数启动线程

C# 使用成员函数启动线程,c#,multithreading,delegates,C#,Multithreading,Delegates,我最近遇到了这样一段代码(这里是简化版,我检查过了,它可以正常工作): 为什么这样的代码在没有编译器抱怨的情况下工作?据我所知,线程应该从静态函数开始。(或无论如何都应传递对对象和成员函数的引用)。但这里我看到的只是传递对成员函数的引用。我好像错过了c#中的一件大事。是否存在传递此引用的隐式方式 UPD:非常感谢。我只想补充一点这个事实。事实证明,编译器会自动处理委托(传递正确的引用对象和方法)。以下是il代码: .method public hidebysig specialname rtsp

我最近遇到了这样一段代码(这里是简化版,我检查过了,它可以正常工作):

为什么这样的代码在没有编译器抱怨的情况下工作?据我所知,线程应该从静态函数开始。(或无论如何都应传递对对象和成员函数的引用)。但这里我看到的只是传递对成员函数的引用。我好像错过了c#中的一件大事。是否存在传递此引用的隐式方式

UPD:非常感谢。我只想补充一点这个事实。事实证明,编译器会自动处理委托(传递正确的引用对象和方法)。以下是il代码:

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       32 (0x20)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  IL_0006:  nop
  IL_0007:  nop
  IL_0008:  ldarg.0
  IL_0009:  ldarg.0
  IL_000a:  ldftn      instance void Rextester.Program/Foo::Loop()
  IL_0010:  newobj     instance void 
[mscorlib]System.Threading.ThreadStart::.ctor(object,

native int)
  IL_0015:  newobj     instance void 
[mscorlib]System.Threading.Thread::.ctor(class 
[mscorlib]System.Threading.ThreadStart)
  IL_001a:  stfld      class [mscorlib]System.Threading.Thread 
Rextester.Program/Foo::thread
  IL_001f:  ret
} // end of method Foo::.ctor
但这里我看到的只是传递对成员函数的引用

文档向客户说明它是一名委托人。它

“表示在线程上执行的方法。
创建托管线程时,在该线程上执行的方法由ThreadStart委托表示“


线程应该从静态函数开始

这不一定是真的。函数不必是静态的

文档显示了这两个示例。使用静态方法和实例方法:

class Test
{
    static void Main() 
    {
        // To start a thread using a static thread procedure, use the
        // class name and method name when you create the ThreadStart
        // delegate. Beginning in version 2.0 of the .NET Framework,
        // it is not necessary to create a delegate explicitly. 
        // Specify the name of the method in the Thread constructor, 
        // and the compiler selects the correct delegate. For example:
        //
        // Thread newThread = new Thread(Work.DoWork);
        //
        ThreadStart threadDelegate = new ThreadStart(Work.DoWork);
        Thread newThread = new Thread(threadDelegate);
        newThread.Start();

        // To start a thread using an instance method for the thread 
        // procedure, use the instance variable and method name when 
        // you create the ThreadStart delegate. Beginning in version
        // 2.0 of the .NET Framework, the explicit delegate is not
        // required.
        //
        Work w = new Work();
        w.Data = 42;
        threadDelegate = new ThreadStart(w.DoMoreWork);
        newThread = new Thread(threadDelegate);
        newThread.Start();
    }
}

class Work 
{
    public static void DoWork() 
    {
        Console.WriteLine("Static thread procedure."); 
    }
    public int Data;
    public void DoMoreWork() 
    {
        Console.WriteLine("Instance thread procedure. Data={0}", Data); 
    }
}
编辑:

关于委托类型,委托人表示:

委托是一种类型,它表示对具有特定参数列表和返回类型的方法的引用

在这里,您可以看到如何使用
new
关键字对其进行实例化:

在声明委托类型后实例化委托,必须创建委托对象并将其与特定方法关联。与所有其他对象一样,将使用新表达式创建新的委托对象

这意味着由于
Loop
ThreadStart
具有相同的返回类型,即
void
和相同的参数列表(此处为空),因此可以使用实例方法
Loop
的名称来重新设置委托

编辑2:

我只是对在没有引用的情况下使用成员函数感到困惑

这是因为您在声明方法的同一类中声明线程

是否存在传递此引用的隐式方式


在这方面,答案是肯定的。如果在类内调用方法或使用名称作为委托(指向方法的指针),则
this
是隐式的。

“应该是静态的”-错误,只有在静态方法中创建时才应该是静态的。请尝试静态构造函数以使其为真<代码>循环因为参数是一个(意味着-编译器会注意正确调用它,例如,如果它是实例成员,则使用
),它不必是静态的。哦,非常感谢。我错过了那个医生。我只是对在没有引用的情况下使用成员函数感到困惑。@lmtinyton不客气。现在我更好地理解了你的问题“是否存在传递此引用的隐含方式?”我编辑了我的帖子并添加了信息。答案是肯定的
class Test
{
    static void Main() 
    {
        // To start a thread using a static thread procedure, use the
        // class name and method name when you create the ThreadStart
        // delegate. Beginning in version 2.0 of the .NET Framework,
        // it is not necessary to create a delegate explicitly. 
        // Specify the name of the method in the Thread constructor, 
        // and the compiler selects the correct delegate. For example:
        //
        // Thread newThread = new Thread(Work.DoWork);
        //
        ThreadStart threadDelegate = new ThreadStart(Work.DoWork);
        Thread newThread = new Thread(threadDelegate);
        newThread.Start();

        // To start a thread using an instance method for the thread 
        // procedure, use the instance variable and method name when 
        // you create the ThreadStart delegate. Beginning in version
        // 2.0 of the .NET Framework, the explicit delegate is not
        // required.
        //
        Work w = new Work();
        w.Data = 42;
        threadDelegate = new ThreadStart(w.DoMoreWork);
        newThread = new Thread(threadDelegate);
        newThread.Start();
    }
}

class Work 
{
    public static void DoWork() 
    {
        Console.WriteLine("Static thread procedure."); 
    }
    public int Data;
    public void DoMoreWork() 
    {
        Console.WriteLine("Instance thread procedure. Data={0}", Data); 
    }
}