Existe alguma maneira de criar um método de thread não estático?

Existe alguma maneira de criar um método de thread não estático no .net? Mostre-me o código por favor.

O código a seguir não funciona:

 ThreadStart ts = delegate {drawFloorAround ();  };
 public void drawFloorAround ()
 {
             ...
 }

Dá este erro -> “Um inicializador de campo não pode referenciar o campo não estático, método ou propriedade”. Se eu mudar o método do static, ele funciona. Mas eu não quero.

… fornece este erro “Um inicializador de campo não pode referenciar o campo, método ou propriedade não estático”.

Leia a mensagem de erro com mais cuidado. Está lhe dizendo precisamente o que está errado. Um inicializador de campo não pode fazer referência a um método não estático . Isso porque o compilador está tentando protegê-lo deste bug:

class C { int foo; int bar = GetBar(); public C(int newFoo) { this.foo = newFoo; } private int GetBar() { return this.foo + 1; } } 

Você faz “new C (123)”. O que é barra definida como? Se este fosse um código legal, então seria definido como 1, não como 124. Por quê? Como o primeiro foo é inicializado como zero, então GetBar () é chamado e, em seguida, o corpo do construtor define this.foo como 123.

Para evitar esse bug, é simplesmente ilegal referenciar um método ou campo de instância em um inicializador de campo.

Agora, você pode razoavelmente apontar que em seu código, você não usa o método de instância, você só faz referência a ele. Você nunca liga mesmo. Isso realmente é seguro. No entanto, as regras do C # são projetadas para serem simples e conservadoras; mesmo que possamos provar que este caso é seguro, tomamos o caminho conservador e simples e dizemos que qualquer referência à instância em um inicializador de campo é ilegal.

Se eu mudar o método para estático, ele funciona.

Corrigir. Nesse caso, o método não depende do estado da instância que ainda não foi configurado.

Mas eu não quero.

OK, então sua única outra opção é parar de usar um inicializador de campo . Coloque a boot no construtor; você assume a responsabilidade de garantir que a boot não use acidentalmente o estado não inicializado.

Se você quer dizer que é possível iniciar um thread com um método não-estático – ou seja, um método de instância – então sim é. Mas as mesmas regras se aplicam a chamar diretamente um método de instância – você só pode fazer isso se tiver uma instância. Por exemplo, se você tem uma instância em uma variável chamada foo então você pode escrever isto:

 ThreadStart ts = delegate { foo.DrawFloorAround(); }; 

Se você ainda não tem uma instância que possa usar, primeiro crie uma:

 ThreadStart ts = delegate { new Foo().DrawFloorAround(); }; 

Se você não quiser criar uma instância, provavelmente seu método deve ser estático.

sim

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

Edit: o problema no código de exemplo é que é um inicializador de campo. Mova este código para um construtor explícito:

 ThreadStart ts; public TypeName() {//constructor ts = this.SomeMethod; } private void SomeMethod() {....} 

Qualquer método pode atuar como um ThreadStart como anúncio de log, não recebe argumentos e retorna nulo. IMO, a opção mais fácil é um método lambda ou anon, pois isso permite encerramentos:

 ThreadStart ts = delegate { someObj.DoSomething(x, y, "z"); }; 

Mas, para um método de instância que retorna void e não recebe argumentos:

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

Então

 var thread = new Thread(ts); 

Os inicializadores são executados antes dos construtores, portanto, você não tem instância para configurá-lo. Defina o valor em seu construtor e você deve estar bem.

 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(); } 

É importante para qualquer um que esteja mudando para o C # do vb.net para notar que as regras mudaram entre o VB.net e o C #. Sob as regras vb.net (IMHO better), os inicializadores são executados entre a chamada para mybase.new e a seguinte declaração do construtor; É permitido que os inicializadores de campo façam referência a campos e propriedades do object atual. Embora isso possa causar problemas se feito de maneira descuidada, ele permite que a boot da variável (e, em alguns casos, a limpeza) seja manipulada no mesmo local no código-fonte da declaração. Qualquer pessoa que migre para o C # precisa reconhecer essa diferença no manuseio do inicializador. Embora seja possível em vb.net descartar adequadamente um iDisposable que é criado em um inicializador, isso não é possível em C # sem um kludge grave usando uma variável threadstatic.