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