2009-09-01 12 views
25

Come condividere i dati tra diversi thread In C# senza utilizzare le variabili statiche? Possiamo creare un tale machanism usando l'attributo?Come condividere i dati tra diversi thread In C# utilizzando AOP?

La programmazione orientata all'aspetto può essere d'aiuto in questi casi?

Per raggiungere il risultato, tutti i diversi thread dovrebbero funzionare su un singolo oggetto?

+2

È possibile accedere a qualsiasi variabile nell'ambito da una discussione. per esempio. 2 thread possono chiamare la stessa funzione e accedere all'istanza del membro/alle variabili statiche. La condivisione è banale, la sincronizzazione dell'accesso alle variabili su più thread è il compito più difficile. – Gishu

+1

Stiamo provando a leggere l'istanza dell'oggetto disponibile in un thread in un altro thread, e abbiamo una restrizione per mantenere la variabile globale/statica, c'è qualche buona idea per ottenerlo? –

+0

Non si accede ai thread in quanto tali. Piuttosto si accede agli oggetti che i thread possono vedere. Se il codice in esecuzione in un thread può accedere a un'istanza dell'oggetto o dati statici, può modificarlo. Se un altro thread può vedere quell'istanza o dati statici, allora hai comunicato tra i due thread. – djna

risposta

5

È possibile passare un oggetto come argomento allo Thread.Start e utilizzarlo come archivio di dati condiviso tra il thread corrente e il thread di avvio.

È anche possibile accedere direttamente (con il blocco appropriato ovviamente) ai membri dei dati, se si è avviato il thread utilizzando il modulo di istanza del delegato ThreadStart.

Non è possibile utilizzare gli attributi per creare dati condivisi tra thread. È possibile utilizzare le istanze di attributo allegate alla classe come memoria di dati, ma non riesco a vedere come sia meglio dell'utilizzo di membri statici o di dati di istanza.

+2

Per utilizzare nuovamente una memoria di dati condivisa è necessario utilizzare una variabile statica/globale? –

+0

Il codice che ha avviato la discussione ha ovviamente un riferimento all'oggetto passato come parametro a Thread.Start. La procedura di thread ha anche un riferimento a quell'oggetto. Quindi, ma pezzi di codice possono scrivere su di esso senza che quell'oggetto debba essere una variabile statica. –

+2

sì .. ho capito ..per favore scrivi qualche frammento di codice per una migliore comprensione –

16

Non si può battere la semplicità di una coda di messaggi bloccata. Dico, non sprecare il tuo tempo con qualcosa di più complesso.

Leggere la dichiarazione blocco.

lock

EDIT

Ecco un esempio dell'oggetto Microsoft Queue avvolto così tutte le azioni contro di essa sono sicuri thread.

public class Queue<T> 
{ 
    /// <summary>Used as a lock target to ensure thread safety.</summary> 
    private readonly Locker _Locker = new Locker(); 

    private readonly System.Collections.Generic.Queue<T> _Queue = new System.Collections.Generic.Queue<T>(); 

    /// <summary></summary> 
    public void Enqueue(T item) 
    { 
     lock (_Locker) 
     { 
      _Queue.Enqueue(item); 
     } 
    } 

    /// <summary>Enqueues a collection of items into this queue.</summary> 
    public virtual void EnqueueRange(IEnumerable<T> items) 
    { 
     lock (_Locker) 
     { 
      if (items == null) 
      { 
       return; 
      } 

      foreach (T item in items) 
      { 
       _Queue.Enqueue(item); 
      } 
     } 
    } 

    /// <summary></summary> 
    public T Dequeue() 
    { 
     lock (_Locker) 
     { 
      return _Queue.Dequeue(); 
     } 
    } 

    /// <summary></summary> 
    public void Clear() 
    { 
     lock (_Locker) 
     { 
      _Queue.Clear(); 
     } 
    } 

    /// <summary></summary> 
    public Int32 Count 
    { 
     get 
     { 
      lock (_Locker) 
      { 
       return _Queue.Count; 
      } 
     } 
    } 

    /// <summary></summary> 
    public Boolean TryDequeue(out T item) 
    { 
     lock (_Locker) 
     { 
      if (_Queue.Count > 0) 
      { 
       item = _Queue.Dequeue(); 
       return true; 
      } 
      else 
      { 
       item = default(T); 
       return false; 
      } 
     } 
    } 
} 

EDIT 2

Spero che questo esempio aiuta. Ricorda che questo è ossa nude. Utilizzando queste idee di base puoi sfruttare in tutta sicurezza la potenza dei thread.

public class WorkState 
{ 
    private readonly Object _Lock = new Object(); 
    private Int32 _State; 

    public Int32 GetState() 
    { 
     lock (_Lock) 
     { 
      return _State; 
     } 
    } 

    public void UpdateState() 
    { 
     lock (_Lock) 
     { 
      _State++; 
     } 
    } 
} 

public class Worker 
{ 
    private readonly WorkState _State; 
    private readonly Thread _Thread; 
    private volatile Boolean _KeepWorking; 

    public Worker(WorkState state) 
    { 
     _State = state; 
     _Thread = new Thread(DoWork); 
     _KeepWorking = true;     
    } 

    public void DoWork() 
    { 
     while (_KeepWorking) 
     { 
      _State.UpdateState();     
     } 
    } 

    public void StartWorking() 
    { 
     _Thread.Start(); 
    } 

    public void StopWorking() 
    { 
     _KeepWorking = false; 
    } 
} 



private void Execute() 
{ 
    WorkState state = new WorkState(); 
    Worker worker = new Worker(state); 

    worker.StartWorking(); 

    while (true) 
    { 
     if (state.GetState() > 100) 
     { 
      worker.StopWorking(); 
      break; 
     } 
    }     
} 
+0

Non è che una coda di messaggi sia adatta a qualsiasi scopo ... – Thorarin

+0

Neanche i messaggi di passaggio? – ChaosPandion

+1

Stiamo provando a leggere l'istanza di oggetto disponibile in un thread in un altro thread, e abbiamo una restrizione per mantenere la variabile globale/statica, c'è qualche buona idea per ottenerlo? –

3

Quando si avvia una discussione si esegue un metodo di una classe scelta. Tutti gli attributi di quella classe sono visibili.

Worker myWorker = new Worker(/* arguments */); 

    Thread myThread = new Thread(new ThreadStart(myWorker.doWork)); 

    myThread.Start(); 

vostro filo è ora nel metodo DoWork() e può vedere alcun attributo di myWorker, che a loro volta possono essere altri oggetti. Ora devi solo stare attento ad affrontare i casi in cui diversi thread hanno colpito tutti quegli attributi nello stesso momento.

+0

yep ..La tua Idea è molto utile, lasciami elaborare la mia situazione qui come Stiamo provando a leggere l'istanza di oggetto disponibile in un thread in un altro thread, e abbiamo una restrizione per mantenere la variabile globale/statica, c'è qualche buona idea per raggiungerlo? –

+0

Non hai elaborato hai semplicemente ripetuto la tua domanda originale. – ChaosPandion

+0

Per favore leggi il mio commento sulla tua domanda. Voglio spiegare ulteriormente, ma ho bisogno del tuo aiuto. – djna

7

Osservare il seguente codice esempio:

public class MyWorker 
{ 
    public SharedData state; 
    public void DoWork(SharedData someData) 
    { 
     this.state = someData; 
     while (true) ; 
    } 

} 

public class SharedData { 
    X myX; 
    public getX() { etc 
    public setX(anX) { etc 

} 

public class Program 
{ 
    public static void Main() 
    { 
     SharedData data = new SharedDate() 
     MyWorker work1 = new MyWorker(data); 
     MyWorker work2 = new MyWorker(data); 
     Thread thread = new Thread(new ThreadStart(work1.DoWork)); 
     thread.Start(); 
     Thread thread2 = new Thread(new ThreadStart(work2.DoWork)); 
     thread2.Start(); 
    } 
} 

In questo caso, la classe filo MyWorker ha una variabile state. Inizializziamo con lo stesso oggetto . Ora puoi vedere che i due lavoratori accedono allo stesso oggetto SharedData. Le modifiche apportate da un lavoratore sono visibili all'altro.

Hai ancora alcuni problemi rimanenti.In che modo worker 2 conosce quando le modifiche sono state apportate dall'operatore 1 e viceversa? Come prevedi modifiche in conflitto? Forse leggi: this tutorial.

+1

Yap..its vicino ma non esatto ..qui due thread bbut stessa istanza della classe myworker, per me due istanze della classe MyWorker (work1 e work2) in thread diversi e voglio leggere i dati da work1 in thread2..come possiamo farlo? –

+0

In tal caso, sarà necessario passare l'oggetto work1 al thread2. È possibile farlo utilizzando ParameterizedThreadStart anziché ThreadStart. – Aamir

+0

@Amir spero che non ti dispiaccia, ho adattato l'esempio per abbinare la descrizione di Jaswant – djna

Problemi correlati