有没有办法在.NET上创建非静态线程方法? 请告诉我代码。
以下代码不起作用:
ThreadStart ts = delegate { drawFloorAround(); };
public void drawFloorAround() { ... }
给出此错误 - > “字段初始值设定项不能引用非静态字段,方法或属性”。 如果我改变方法做静态,它的工作原理。但我不想。
答案 0 :(得分:10)
...给出此错误“字段初始化程序无法引用非静态字段,方法或属性”。
仔细阅读错误消息。它告诉你究竟出了什么问题。 字段初始值设定项无法引用非静态方法。那是因为编译器试图保护您免受此错误的影响:
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#的规则设计简单而保守;尽管我们可以证明这种情况是安全的,但我们采用保守的简单路径并说明对字段初始化程序中的实例的任何引用都是非法的。
如果我将方法更改为静态,则可以正常工作。
正确。在这种情况下,该方法不依赖于尚未建立的实例状态。
但我不想。
好的,那么你唯一的另一个选择是停止使用字段初始值设定项。将初始化放在构造函数中;然后你负责确保初始化不会意外地使用未初始化的状态。
答案 1 :(得分:7)
如果你的意思是是否可以使用非静态方法启动一个线程 - 即一个实例方法 - 那么它就是。但是相同的规则适用于直接调用实例方法 - 只有拥有实例才能执行此操作。例如,如果您在名为foo
的变量中有一个实例,那么您可以这样写:
ThreadStart ts = delegate { foo.DrawFloorAround(); };
如果您还没有可以使用的实例,则必须先创建一个:
ThreadStart ts = delegate { new Foo().DrawFloorAround(); };
如果您不想创建实例,那么您的方法可能应该是静态的。
答案 2 :(得分:4)
是
public class DoSomthing
{
public void Do()
{
Thread t = new Thread(DoInBackground);
t.Start();
}
public void DoInBackground()
{
// ....
}
}
答案 3 :(得分:2)
编辑:示例代码中的问题是它是字段初始化程序。将此代码移动到显式构造函数:
ThreadStart ts;
public TypeName() {//constructor
ts = this.SomeMethod;
}
private void SomeMethod() {....}
任何方法都可以作为日志广告充当ThreadStart,它不需要args并返回void。 IMO最简单的选择是lambda或anon方法,因为它允许闭包:
ThreadStart ts = delegate {
someObj.DoSomething(x, y, "z");
};
但对于返回void且不带args的实例方法:
var obj = /* init obj */
ThreadStart ts = obj.SomeMethod;
然后
var thread = new Thread(ts);
答案 4 :(得分:0)
初始化程序在构造函数之前运行,因此您没有实例将其设置为。在构造函数中设置值,你应该没问题。
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();
}
答案 5 :(得分:0)
对于从vb.net迁移到C#的人来说,注意VB.net和C#之间的规则已经改变是很重要的。在vb.net(更好的恕我直言)规则下,初始化程序在mybase.new的调用和构造函数的以下语句之间运行;字段初始值设定项允许引用当前对象的字段和属性。虽然如果不小心这样做会导致问题,但它允许在源代码中与声明相同的地方处理变量初始化(在某些情况下清理)。迁移到C#的任何人都需要识别初始化程序处理中的这种差异。虽然在vb.net中可以正确处理在初始化程序中创建的iDisposable,但如果没有使用threadstatic变量的严重kludge,这在C#中是不可能的。