Záleží na konkrétním scénáři. Podle délky lze ale odlišit dva typy operací: 1) Short-Running operace Pro krátké operace se v první řadě vůbec nedoporučuje vytvářet vlastní vlákno. Doporučený způsob je používat třídu Task, knihovnu TPL a obdobné principy vyšší úrovně abstrakce. Objekt Task, reprezentuje stav dané operace a v závislosti na konkrétním scénáři může sloužit ke zjišťování např. zda operace již skončila (a zda úspěšně), cancelování apod. 2) Long-Running operace Pro dlouho běžící operace může mít smysl (vhledem k vysoké režii) vytvářet vlastní vlákno. Protože se ale jedná o dlouho běžící operaci nebude mít pravděpodobně s metodou, která jej vytvořila co se týče životnosti nic společného tj. vlákno bude žít dlouho potom co tato metoda skončila. Nicméně i u takové operace potřebujeme velmi často řešit nějakou interakci operace s okolím. Například se může jednat o nějaký interní logický proces nějaké komponenty, který běží pořád dokud do komponenta sama neukončí. Jindy je potřeba reportovat, že operace stále běží apod. Ve všech těchto případech bych vlastní vlákno zapouzdřil do vlastní třídy, která bude řešit jeho životní cyklus a interakci s okolím. Například pro případ vlákna s životností stejnou jako komponenta, bych příslušnou třídu udělal IDisposable:
internal sealed class Process : IDisposable
{
private readonly CancellationTokenSource ProcessCancellation;
private readonly Thread ProcessThread;
private bool IsDisposed;
public Process()
{
this.ProcessCancellation = new CancellationTokenSource();
this.ProcessThread = new Thread(() => ProcessThreadProc(this.ProcessCancellation.Token));
this.ProcessThread.Start();
}
public void Dispose()
{
if (!this.IsDisposed)
{
this.ProcessCancellation.Cancel();
this.ProcessThread.Join();
this.ProcessThread.Dispose();
this.IsDisposed = true;
}
}
private static void ProcessThreadProc(CancellationToken cancelToken)
{
while (true)
{
if (cancelToken.IsCancellationRequested)
{
return;
}
//...
}
}
}
|