2015-06-01 10 views
5

Wszystkie artykuły w Internecie mówią, że używanie Thread.Abort jest złe (ponieważ prymitywy synchronizacji należą do systemu operacyjnego, a proces nie kończy się jeszcze, a prymitywy mogą pozostać zablokowane po przerwaniu wątku). Deweloperzy zalecają zamiast tego zakończyć całe procesy, ponieważ system operacyjny zwolni prymitywy synchronizacji po zatrzymaniu procesu.Smukłe klasy synchronizacji są na AppDomain lub na proces?

  1. Will AppDomain rozładunek pomoc, Jeśli będzie użyć Slim synchronizacji prymitywów? (W .net 4.0 dodano kilka nowych klas związanych z wątkami: ManualResetEventSlim, SemaphoreSlim, ReaderWriterLockSlim).

    Dokumentacja mówi, że te prymitywy nie mogą być używane między różnymi procesami, ponieważ kod implementujący prymitywy jest w pełni zarządzany. Ale nie rozumiem - czy te prymitywy będą działały przez granicę AppDomain. (patrz Can't set synchronization context when using appdomains)

  2. Jeśli tak, jak to robią? Jeśli nie, to dlaczego dokumentacja pomija to ograniczenie?

UPD: Cały mój kod jest mi zaufany, łącznie z kodem wewnątrz domeny, który rozładowuję. Nie chcę, aby wątek działał, kiedy nadejdzie czas, aby go zakończyć. Chcę zakończyć (przerwać) wątek zamiast "ustawiania flagi" i "tworzenia ładnej architektury". Jeśli jest to konieczne, aby utworzyć dodatkowy wątek pierwszy (myślę, że jest to konieczne na początku przetwarzania w tle w oddzielnej domenie, aby utworzyć jeszcze jeden wątek), zrobię to. Nie chcę używać podejścia "ustawianie flag", ponieważ wymaga mnie do algorytmu tła instrumentu z kontroli flagi, nie powinienem, to runtime lub kompilator powinien zautomatyzować tę oprzyrządowanie dla mnie. W tej chwili nie ma takiej oprzyrządowania, dlatego próbuję zastosować podejście z rozładowaniem domen.

Dodanie czeków między każdą instrukcją (lub w głęboko zagnieżdżonych cyklach) znacznie spowolni kod. Dodanie czeku w losowych lokalizacjach nie daje gwarancji szybkiego zakończenia. Jeśli trudności z pisaniem bezpiecznego kodu można rozwiązać, dlaczego nie spróbować przerwać wątki i rozładować domenę?

+1

Jak byś je przez granicę AppDomain? Nie można ich przekształcać do postaci szeregowej, ani nie dziedziczą z 'MarshalByRefObject'. –

+2

AppDomain rozwiązuje ten problem. Ale używanie prymitywów synchronizacji w aplikacjach nie działa, musisz mieć możliwość wyrzucenia * wszystkiego *. –

+0

Jest więcej problemów związanych z opcją "Thread.Abort" niż te, o których wspomniałeś (w rzeczywistości niektóre prymitywy synchronizacji są wypuszczane dobrze z opcją "Thread.Abort', pod warunkiem, że wątek faktycznie umiera oczywiście). Pytanie brzmi, dlaczego próbujesz użyć agresywnej aborcji zamiast unieważniania? Wystarczy wysłać sygnał i niech wątek decyduje, kiedy można bezpiecznie przerwać. Pisanie bezpiecznego kodu jest znacznie trudniejsze niż zwykłego kodu wątku - zarówno dla zarządzanych, jak i natywnych zasobów. – Luaan

Odpowiedz

2

Ty nie rozumie się AppDomain, Process i Thread definicje - AppDomains always lives in one process, but one process can be a master for different AppDomains *:

Możliwość uruchamiania wielu aplikacji w ramach jednego procesu dramatycznie zwiększa skalowalność serwera.

  • ten jest podobny do Thread, tylko na wzmiankę.

więc odpowiedź na Twoje pytanie jest Tak The slim synchronization primitives będzie współpracować z różnymi AppDomains, ponieważ nie ma żadnych połączeń cross-procesowe w takiej architekturze, tylko logiczne rozróżnienie dla różnych procesów.

chodzi o powiązanego pytanie, nie ma problemu z prymitywów tam synchronizacji tylko z SynchronizationContext, który jest Thread -specyficznych, ale nie AppDomain -specyficznych.

można znaleźć wielką odpowiedź na temat różnicy między AppDomain, Thread i Process tutaj: Difference between AppDomain, Assembly, Process, and a Thread

jak dla rozładunku AppDomain, myślę, że można byłaby kod, jak można zacząć pracownika Thread do swojej AppDomain z ograniczonym dostępem do zasobów systemowych, i po prostu czekać na to, aby być gotowy, coś it mentioned here:

using System; 
using System.Threading; 
using System.Threading.Tasks; 

class Program 
{ 
    static void Main() 
    { 
     var ad = AppDomain.CreateDomain("WhereTheWorkHappens"); 

     Task<string> t = DoWorkInOtherDomain(ad); 
     Console.WriteLine("waiting..."); 
     Console.WriteLine(t.Result); 

     Console.ReadLine(); 
    } 

    static Task<string> DoWorkInOtherDomain(AppDomain ad) 
    { 
     var ch = new MarshaledResultSetter<string>(); 

     Worker worker = (Worker)ad.CreateInstanceAndUnwrap(typeof(Worker).Assembly.FullName, typeof(Worker).FullName); 
     worker.DoWork(ch); 

     return ch.Task; 
    } 

    class Worker : MarshalByRefObject 
    { 
     public void DoWork(MarshaledResultSetter<string> callback) 
     { 
      ThreadPool.QueueUserWorkItem(delegate 
      { 
       Thread.SpinWait(500000000); 
       callback.SetResult(AppDomain.CurrentDomain.FriendlyName); 
      }); 
     } 
    } 

    class MarshaledResultSetter<T> : MarshalByRefObject 
    { 
     private TaskCompletionSource<T> m_tcs = new TaskCompletionSource<T>(); 
     public void SetResult(T result) { m_tcs.SetResult(result); } 
     public Task<T> Task { get { return m_tcs.Task; } } 
    } 
} 

Jako dodatkowy pomysł, można przeczytać o Sandboxing your code with TPL, które, jak sądzę, jest lepszym rozwiązaniem, ponieważ nie zarządzasz ręcznie zasobami systemu i ma mniejsze szanse na zhakowanie przez niezaufany kod.

Ponadto, można znaleźć projekt GitHub z Cross-AppDomain Marshaling friendly TPL wrappers for APM

+0

Rozumiem, że AppDomain należy tylko do jednego procesu, a AppDomain nie obejmuje kilku procesów. Rozumiem, że SynchronizationContext (dla ContextBoundObjects) nie obejmuje kilku AppDomains. Dlaczego decydujesz, że nie? Wygląda na to, że walczyłeś ze swoimi dawnymi nieporozumieniami, zakładając, że mam to samo. Moje są różne! Nie rozumiem, jak synchronizować między domenami aplikacji (bez korzystania z prymitywów synchronizacji na poziomie systemu operacyjnego). Nadal nie rozumiem, co dzieje się z wątkiem, gdy przekracza granicę AppDomain. – R2D4

+0

Spójrz na to pytanie - http://stackoverflow.com/questions/21493944/synchronizing-between-appdomains-using-named-mutex Myślę, że pytanie jest sformułowane nieprawidłowo. Synchronizujemy wątki, a nie AppDomain. Ale wątki należą do Procesów, a nie do AppDomains. – R2D4

+0

Odpowiedziałem na twoje pytanie: Tak, cienkie wersje będą działać w różnych 'AppDomain' tak długo, jak różne' Wątki', ponieważ nadal są w ** tym samym 'Procesie' **. – VMAtm

Powiązane problemy