2015-04-25 15 views
8

ho alcuni dubbi per quanto riguarda l'istruzione using:usando utilizzo dichiarazione in C#

ho una classe denominata

MyJob che è usa e getta. Poi ho anche una proprietà su MyJob JobResults che è anche Usa e getta.

MY codice:

using (MyJob job = new MyJob()) 
{ 
    //do something. 
    FormatResults(job.JobResults) 
} 

public string FormatResuls(JobResuts results) 
{ 
} 

mia prima domanda è: In questo caso, dopo il blocco utilizzando sono entrambi MyJob e MyJob.Results smaltiti o solo MyJob e NON MyJob.Results?

sto svolgendo anche l'elaborazione parallela w.r.t Compiti in C#:

Tasks allTasks = List<Tasks> 

try 
{ 
    foreach(Task t in allTasks) 
    { 
     // Each tasks makes use of an IDisposable object. 
     t.Start(); 
    } 
    Task.WaitAll(allTasks); 
} 
catch(AggregateExecption aex) 
{ 
    /// How do I ensure that all IDisposables are disposed properly if  an exception happens in any of the tasks? 
} 

Il mio secondo q, nel codice di cui sopra, qual è il modo corretto per garantire a smaltire correttamente gli oggetti quando la gestione delle eccezioni in compiti?

Scusate se le mie domande sono troppo ingenue o confuse, come sto ancora cercando di imparare e capire C#. Grazie ragazzi!

+8

1. Stai facendo due domande in una: in realtà non è un formato consigliato su [SO]. 2. Sulla prima domanda: non sappiamo come è progettata la tua classe. O stai chiedendo se si dovrebbe disporre di oggetti annidati o no? –

+1

Dipende da come la tua classe MyJob implementa IDisposable .. –

+0

Dipende da come la tua classe MyJob implementa IDisposable .. Assicurati di seguire lo schema corretto ... [link] (https://msdn.microsoft.com/en -us/library/ms244737.aspx) –

risposta

5

sono entrambi MyJob e MyJob.Results eliminati o solo MyJob e NON MyJob.Results?

Ciò è soggettivo all'implementazione del metodo Dispose. Dato che non l'abbiamo visto nella tua domanda, presumo che tu non stia attualmente smaltendo la tua proprietà Result in MyJob.Dispose, quindi sarà quest'ultima.

Come è avvolto solo MyJob in una dichiarazione using, e ancora una volta ammesso che non fa nulla per la vostra proprietà Result, esso sarà disposto in contrapposizione a Results, che non è avvolto in un comunicato using.

Si può decidere che MyJob, poiché incapsula la proprietà Result, è responsabile anche per il disposable di esso. Se si decide in tal modo, è possibile smaltire Results in MyJobs.Dispose.

qual è il modo corretto per garantire di smaltire correttamente gli oggetti quando gestisce le eccezioni nelle attività?

Se il delegato, che è passato al Task è avvolto in un comunicato using, sei al sicuro, dal momento che using trasformerà il vostro codice per un blocco try-finally, se si verifica un'eccezione nella vostra using blocco, il blocco finally sarà eseguire ancora yourObject.Dispose.

+0

Come le altre risposte dicono, se chiama Results.Dispose nel metodo MyJob.Dispose, sarà effettivamente eliminato, quindi la parte superiore è vera solo se non la dispone esplicitamente nell'oggetto MyJob. –

+0

@RonBeyer Hai ragione, ho modificato la mia risposta proprio come hai postato il commento :) –

+0

Non credo che "tu possa decidere" sia la dicitura giusta. Il modello indica chiaramente che nei vari metodi 'Dispose()' hai ** di disporre di risorse usa e getta, il che significa che 'MyJob' deve disporre di qualsiasi' JobResult' che * abbia * (in un * ha-a * relazione). Non c'è spazio per l'interpretazione nella documentazione vera e propria. – pid

0

1) Il modo migliore è smaltire JobResults all'interno del metodo Dispose() di MyJob. Altrimenti non è smaltito da solo

2) Vorrei implementare la parte finally, passare attraverso ogni oggetto e smaltirlo. Ma nella maggior parte dei casi non è necessario farlo read this

2

Solo MyJobs è eliminato.Per altre proprietà, è necessario comprendere la proprietà dell'oggetto: chi possiede l'oggetto dovrebbe essere responsabile (in generale) di eliminarlo. Una proprietà che implementa IDisposable potrebbe essere utilizzata da altre istanze, quindi è possibile eliminarla solo se si è quella che l'ha creata e non ci sono altri riferimenti ad essa, oppure la classe fallisce con grazia se sa che è stata eliminata.

2

Qui ci sono molte buone risposte ma una cosa rimane. Se si vuole essere certi che l'oggetto sia ben disposto perché utilizza risorse non gestite, è necessario implementare un distruttore in oggetto, come:

class MyJob : IDisposable 
{ 
    private bool _disposed = false; 
    protected virtual void Dispose(bool disposing) 
    { 
      if (!_disposed) 
      { 
       //Dispose unmanaged resources and any child disposables here 
      } 
    } 

    void Dispose() 
    { 
      this.Dispose(true); 
      GC.SuppressFinalize(this); 
    } 

    ~MyJob() 
    { 
      //ONLY use if you have unmanaged resources that DO NOT 
      //implement their own finalizers. 
      Dispose(); 
    } 
} 

Tuttavia, si consiglia di NON utilizzare un finalizzatore (distruttore) a meno che non si stia finalizzando un tipo con risorse non gestite che non includono il proprio finalizzatore.

Vedere https://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx per le migliori pratiche sull'implementazione di IDisposable.

+0

Due cose. Innanzitutto, non raccomanderei l'implementazione di un finalizzatore, specialmente quando non sappiamo dalla domanda dell'OP se si tratta di risorse non gestite. In secondo luogo, anche se finisci per implementare un finalizzatore, dovresti chiamare 'GC.SuppressFinalizer (this)' nel tuo metodo 'Dispose (bool disposing)'. –

+0

@YuvalItzchakov Ho modificato per includere la soppressione finalizzazione della chiamata, l'ho perso. Ho detto sotto il post di non implementarlo a meno che non vengano soddisfatte alcune condizioni specifiche e il link MSDN mostra molte buone pratiche durante l'implementazione. Stavo solo mostrando un esempio completo assumendo risorse non gestite senza i loro finalizzatori. –

+0

Non fraintendetemi, non sono d'accordo sul problema del finalizzatore, è importante sapere che esiste una cosa del genere. Sto solo dicendo che data la piccola quantità di dettagli nella domanda, non vorrei eseguire l'implementazione di un finalizzatore :) –