Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.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# .NET-有没有办法创建非静态线程方法?_C#_.net_Multithreading - Fatal编程技术网

C# .NET-有没有办法创建非静态线程方法?

C# .NET-有没有办法创建非静态线程方法?,c#,.net,multithreading,C#,.net,Multithreading,有没有办法在.NET上创建一个非静态线程方法? 请给我看代码 以下代码不起作用: ThreadStart ts = delegate { drawFloorAround(); }; ThreadStart ts=委托{DrawFloorRound();}; 公共区域 { ... } 给出此错误->“字段初始值设定项无法引用非静态字段、方法或属性”。 如果我更改方法do static,它就会工作。但是我不想编辑:示例代码中的问题是它是一个字段初始化器。将此代码移动到显式构造函数: ThreadSt

有没有办法在.NET上创建一个非静态线程方法? 请给我看代码

以下代码不起作用:

ThreadStart ts = delegate { drawFloorAround(); }; ThreadStart ts=委托{DrawFloorRound();}; 公共区域 { ... } 给出此错误->“字段初始值设定项无法引用非静态字段、方法或属性”。
如果我更改方法do static,它就会工作。但是我不想编辑:示例代码中的问题是它是一个字段初始化器。将此代码移动到显式构造函数:

ThreadStart ts;
public TypeName() {//constructor
    ts = this.SomeMethod;
}
private void SomeMethod() {....}
任何方法都可以像日志一样充当ThreadStart,它不接受任何参数并返回void。IMO最简单的选择是lambda或anon方法,因为这允许闭包:

ThreadStart ts = delegate {
    someObj.DoSomething(x, y, "z");
};
但对于返回void且不带参数的实例方法:

var obj = /* init obj */
ThreadStart ts = obj.SomeMethod;
然后

如果您的意思是可以使用非静态方法(即实例方法)启动线程,那么是的。但同样的规则也适用于直接调用实例方法——只有在拥有实例的情况下才能这样做。例如,如果在名为
foo
的变量中有一个实例,则可以编写以下代码:

ThreadStart ts = delegate { foo.DrawFloorAround(); };
如果您还没有可以使用的实例,则必须首先创建一个:

ThreadStart ts = delegate { new Foo().DrawFloorAround(); };
如果您不想创建实例,那么您的方法可能应该是静态的。

    public class DoSomthing
    {

        public void Do()
        {
            Thread t = new Thread(DoInBackground);
            t.Start();
        }

        public void DoInBackground()
        {
            // ....
        }

    }

初始值设定项在构造函数之前运行,因此您没有可将其设置为的实例。在构造函数中设置该值,您应该可以

class DoesNotWork {
    public Action ts = Frob; // doesn't work, cannot access non-static method 
    void Frob() { }
}
class ThisIsFine {
    public Action ts;
    public ThisIsFine() { ts = Frob; }
    void Frob();
}
。。。给出此错误“字段初始值设定项无法引用非静态字段、方法或属性”

请更仔细地阅读错误消息。它准确地告诉你什么是错的。字段初始值设定项不能引用非静态方法。这是因为编译器试图保护您免受此错误的影响:

class C
{
    int foo;
    int bar = GetBar();
    public C(int newFoo)
    {
        this.foo = newFoo;
    }
    private int GetBar() { return this.foo + 1; }
}
你做“新C(123)”。酒吧的设置是什么?如果这是法律代码,那么它将被设置为1,而不是124。为什么?因为第一个foo被初始化为零,然后调用GetBar(),然后构造函数体将this.foo设置为123

为了防止此错误,在字段初始值设定项中引用实例方法或字段是非法的

现在,您可以合理地指出,在代码中,您不使用实例方法,只引用它。你从来没有真正叫过它。这实际上是安全的。然而,C#的规则设计得简单而保守;尽管我们可以证明这种情况是安全的,但我们采取保守、简单的方法,并说在字段初始值设定项中引用实例是非法的

如果我将该方法更改为static,它就会工作

对。在这种情况下,该方法不依赖于尚未设置的实例状态

但我不想


好的,那么您唯一的选择就是停止使用字段初始值设定项。将初始化放在构造函数中;然后,您负责确保初始化不会意外使用未初始化状态。

对于从vb.net移动到C的任何人来说,重要的是要注意规则在vb.net和C#之间发生了更改。根据vb.net(IMHO更好)规则,初始化程序在调用mybase.new和构造函数的以下语句之间运行;允许字段初始值设定项引用当前对象的字段和属性。虽然如果不小心这样做可能会导致问题,但它允许在源代码中与声明相同的位置处理变量初始化(在某些情况下还包括清理)。任何迁移到C#的人都需要认识到初始值设定项处理中的这种差异。虽然在vb.net中可以正确处理在初始值设定项中创建的iDisposable,但在C#中,如果没有使用threadstatic变量的严重混乱,则不可能正确处理iDisposable。

这不起作用。我将在会议上提供更多细节question@Alan-在第二个示例中,只需将SomeMethod替换为方法名:drawFloorAround。不包含左侧的对象(可能是“this”)。您只需要对drawFloorAround()的对象进行引用@菲利普:不,那也不行;如果对象是“this”,这似乎是预期的,那么同样的错误也会发生。不能在字段初始值设定项中引用“this”。是。。。确切地我希望我能给你两张赞成票,这对我很有效。新的Foo().DrawFloorRound。。非常感谢。方法应该是静态的。但是在我调用canvas的方法中,静态的东西有问题。。。以上所有的答案对我来说都是无用的。我不知道在构造函数中初始化某些东西与在外部初始化有什么区别。
class DoesNotWork {
    public Action ts = Frob; // doesn't work, cannot access non-static method 
    void Frob() { }
}
class ThisIsFine {
    public Action ts;
    public ThisIsFine() { ts = Frob; }
    void Frob();
}
class C
{
    int foo;
    int bar = GetBar();
    public C(int newFoo)
    {
        this.foo = newFoo;
    }
    private int GetBar() { return this.foo + 1; }
}