2010-12-10 15 views
5

C'è un modo per creare un metodo di thread non statico su .NET? Mostrami il codice per favore..NET: esiste un modo per creare un metodo di thread non statico?

Il seguente codice non funziona:

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

dà questo errore -> "Un inizializzatore di campo non può fare riferimento il campo non statico, metodo o proprietà". Se cambio il metodo faccio statico, funziona. Ma io non voglio.

+0

mostrami il codice per favore. – Seva

+1

hai solo bisogno di un riferimento all'oggetto per drawFloorAround(); – phillip

+2

@philip: No, non funziona neanche; se l'oggetto è "questo", che sembra essere destinato a essere, allora si verificherà lo stesso errore. * Non è possibile fare riferimento a "questo" in un inizializzatore di campo. * –

risposta

2

Modifica: il problema nel codice di esempio è che è un inizializzatore di campo. Spostare il codice a un costruttore esplicito:

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

qualsiasi metodo può agire come un ThreadStart come annuncio di registro che non prende argomenti e restituisce void. IMO l'opzione più semplice è un metodo lambda o anon come questo permette chiusure:

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

Ma per un metodo di istanza che restituisce vuoto e non si assume alcuna args:

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

Poi

var thread = new Thread(ts); 
+0

non funziona. Fornirò maggiori dettagli alla domanda – Seva

+0

@Alan - nel secondo esempio sostituiremo SomeMethod con il nome del metodo: drawFloorAround. Nulla da includere l'oggetto a sinistra (che potrebbe essere "questo"). –

+0

@Alan - Vedo ora; aggiornamento risposta ... –

5

Se si intende è possibile avviare una discussione con un metodo non statico, ovvero un metodo di istanza, quindi sì. Ma si applicano le stesse regole di chiamare direttamente un metodo di istanza: puoi farlo solo se hai un'istanza. Ad esempio, se si dispone di un caso in una variabile denominata foo allora si può scrivere questo:

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

Se non si dispone già di un esempio che è possibile utilizzare, quindi è necessario creare uno:

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

Se non si desidera creare un'istanza, il metodo probabilmente dovrebbe essere statico.

+0

sì ... esattamente ... vorrei poterti dare 2 voti per quello. – phillip

+0

questo ha funzionato per me. Il nuovo Foo(). DrawFloorAround .. grazie. Il metodo dovrebbe essere statico. Ma all'interno del metodo sto chiamando una tela, quindi ha problemi con le cose statiche. – Seva

4

public class DoSomthing 
    { 

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

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

    } 
0

Inizializzatori eseguire prima i costruttori, in modo da avere alcuna istanza per impostarlo. Imposta il valore nel tuo costruttore e dovresti essere a posto.

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

... dà questo errore "Un inizializzatore campo non può fare riferimento il campo non statico, metodo o proprietà".

Leggere più attentamente il messaggio di errore. Ti sta dicendo esattamente cosa c'è che non va. Un inizializzatore di campo non può fare riferimento a un metodo non statico . Questo perché il compilatore sta cercando di proteggere l'utente da questo bug:

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

Fate "nuova C (123)". A cosa serve la barra? Se questo fosse codice legale, sarebbe impostato su 1, non su 124. Perché?Poiché first foo viene inizializzato a zero, viene chiamato GetBar(), quindi il corpo del costruttore imposta this.foo a 123.

Per evitare questo bug è semplicemente illegale fare riferimento a un metodo o campo di istanza in un inizializzatore di campo.

Ora, si potrebbe ragionevolmente sottolineare che nel codice, non lo fai uso il metodo di istanza, è solo riferimento esso. In realtà non è mai chiamare it. Questo in realtà è sicuro. Tuttavia, le regole di C# sono progettate per essere semplici e prudenti; anche se potremmo dimostrare che questo caso è sicuro, prendiamo la strada semplice e prudente e diciamo che il numero del riferimento all'istanza in un inizializzatore di campo è illegale.

Se cambio il metodo in statico, funziona.

Corretto. In tal caso, il metodo non dipende dallo stato dell'istanza che non è stato ancora impostato.

Ma io non voglio.

OK, allora la vostra unica altra scelta è quella di fermata utilizzando un campo di inizializzazione. Metti l'inizializzazione nel costruttore; quindi si assume la responsabilità di garantire che l'inizializzazione non utilizzi accidentalmente lo stato non inizializzato.

0

È importante per chiunque si sposti in C# da vb.net per notare che le regole sono cambiate tra VB.net e C#. Sotto le regole vb.net (IMHO meglio), gli inizializzatori funzionano tra la chiamata a mybase.new e la seguente dichiarazione del costruttore; è consentito agli inizializzatori di campo fare riferimento ai campi e alle proprietà dell'oggetto corrente. Mentre questo può causare problemi se fatto con noncuranza, consente l'inizializzazione delle variabili (e in alcuni casi la pulizia) da gestire nello stesso punto del codice sorgente della dichiarazione. Chiunque esegua la migrazione a C# deve riconoscere questa differenza nella gestione dell'inizializzatore. Mentre in vb.net è possibile disporre correttamente un iDisposable creato in un inizializzatore, ciò non è possibile in C# senza un kludge grave che utilizza una variabile threadstatic.

Problemi correlati