Sdílet prostřednictvím


Podproces synchronizace (C# a Visual Basic)

Následující oddíly popisují funkcí a tříd, které lze synchronizovat přístup k prostředkům ve víceprocesových aplikacích.

Jednou z výhod použití více podprocesů aplikace je každý podproces spuštěn asynchronně.Pro aplikace systému Windows díky časově náročné úkoly provádět na pozadí při okna aplikace a řídí zůstat reagovat.Aplikace s více podprocesy pro server poskytuje schopnost zpracovávat příchozí požadavek jiný podproces.Jinak by získat každý nový požadavek na servis není dokud předchozí žádost byla plně spokojeni.

Asynchronní povaze podprocesů znamená, že přístup k prostředkům jako popisovače souborů, síťová připojení a paměť však musí být koordinovány.Jinak by dva či více podprocesů přístup stejný zdroj současně vědoma každé akce jiných uživatelů.Výsledkem je poškození dat nepředvídatelné.

Pro jednoduché operace na nedílnou číselné typy synchronizace podprocesů lze provést s členy Interlocked třídy.Pro všechna data typů a prostředky nejsou bezpečné podproces multithreading lze bezpečně provést pouze pomocí prvků v tomto tématu.

Základní informace o programování s více podprocesy viz:

Zámek a SyncLock klíčová slova

lock (C#) a SyncLock (Visual Basic) příkazy lze zajistit blok kódu dokončena bez přerušení jiné podprocesy.To lze provést po dobu trvání bloku kódu získání zámku vzájemné vyloučení pro daný objekt.

A lock nebo SyncLock prohlášení je uveden objekt jako argument a následuje blok kódu, který se má provádět současně pouze jeden podproces.Příklad:

Public Class TestThreading
    Dim lockThis As New Object

    Public Sub Process()
        SyncLock lockThis
            ' Access thread-sensitive resources.
        End SyncLock
    End Sub
End Class
public class TestThreading
{
    private System.Object lockThis = new System.Object();

    public void Process()
    {

        lock (lockThis)
        {
            // Access thread-sensitive resources.
        }
    }

}

Argument poskytnuty lock klíčové slovo musí být objekt na základě typu odkazu a slouží k definování rozsahu zámku.V příkladu výše je omezena na tuto funkci zámku oboru, protože žádné odkazy na objekt lockThis existují vně funkce.Pokud odkaz, zámku oboru by rozšíření daného objektu.Přesně řečeno objektu, pokud slouží výhradně k jedinečné identifikaci prostředku sdílení mezi více podprocesů, což může být instance libovolné třídy.V praxi však tento objekt obvykle představuje prostředek pro podproces, který je nutné synchronizace.Například pokud je objekt kontejneru pro více podprocesů, pak mohou být předány kontejneru Zamknout a synchronizované kód bloku po uzamčení by přístup kontejneru.Jako další podprocesy zamkne na stejné obsahovat před přístupem a přístup k objektu bezpečně synchronizovány.

Obecně je nejlepší zabránit uzamčení na public typu, nebo na instance objektu mimo kontrolu vaší aplikace.Například lock(this) může být problematické, pokud je instance, veřejně přístupná, protože objekt také může uzamknout kód mimo vaši kontrolu.Vytvořit toto zablokování situace, kdy dva či více podprocesů čekat na vydání stejného objektu.Uzamčení na veřejné datový typ, jako protiklad k objektu, může způsobit problémy z téhož důvodu.Blokování literály je zvláště riskantní, protože literál řetězce jsou interned podle společného jazykového modulu runtime (CLR).To znamená, že existuje jedna instance dané řetězec literálu pro celý program přesně stejný objekt představuje literál ve všech aplikačních doménách se systémem všechny podprocesy.Výsledkem zámek umístěny na řetězec se stejným obsahem kdekoli v procesu uzamčení aplikace všechny výskyty řetězce v aplikaci.Proto je vhodné zamknout soukromé nebo chráněné člen, který není interned.Některé třídy poskytují členové speciálně pro zamykání.Array Typu, například poskytuje SyncRoot.Poskytují mnoho typů kolekce SyncRoot i člen.

Další informace o lock a SyncLock příkazy, naleznete v následujících tématech:

Monitory

Stejně jako lock a SyncLock klíčová slova, monitory zabránit bloky kódu ze současné spuštění více podprocesů.Enter Metoda umožňuje pouze jednu podproces pokračovat do následující příkazy; všechny podprocesy zablokovány až do provádění volání podprocesu Exit.Toto je stejně jako použití lock klíčové slovo.Příklad:

SyncLock x
    DoSomething()
End SyncLock
lock (x)
{
    DoSomething();
}

Jedná se o ekvivalent:

Dim obj As Object = CType(x, Object)
System.Threading.Monitor.Enter(obj)
Try
    DoSomething()
Finally
    System.Threading.Monitor.Exit(obj)
End Try
System.Object obj = (System.Object)x;
System.Threading.Monitor.Enter(obj);
try
{
    DoSomething();
}
finally
{
    System.Threading.Monitor.Exit(obj);
}

Použití lock (C#) nebo SyncLock klíčové slovo (Visual Basic) má obvykle přednost použití Monitor třídy přímo, oba protože lock nebo SyncLock je stručnější a protože lock nebo SyncLock zajistí, že je vydána podkladové monitor, i v případě, že chráněný kód výjimku.Tím se dosahuje finally klíčové slovo provede jeho přidružený kód bloku bez ohledu na to, zda je vyvolána výjimka.

Události synchronizace a úchyty čekání

Pomocí uzamčení nebo monitoru je užitečné pro zabránění současné spuštění podprocesu citlivé bloky kódu, ale tyto konstrukce neumožňuje jeden podproces komunikaci na jiné události.To vyžaduje události synchronizace, které jsou objekty, které mají jednu z dvou států signalizovaném a un-signaled, který slouží k aktivaci a pozastavit podprocesů.Podprocesů může být pozastaveno provádí čekání na událost synchronizace, který je unsignaled a lze ji aktivovat změnou stavu události signalizováno následným tichem.Pokud se pokusí podproces čeká na událost, která je již signalizováno následným tichem, podproces pokračuje provést neprodleně.

Existují dva typy událostí synchronizace: AutoResetEvent, a ManualResetEvent.Liší se pouze v tomto AutoResetEvent signalizováno následným změny z tichem na unsignaled automaticky pokaždé, když se aktivuje podproces.Naopak ManualResetEvent umožňuje libovolný počet podprocesů, které lze aktivovat signalizovaném stavu a bude pouze vrátit unsignaled státu při jeho Reset je volána metoda.

Podprocesy je třeba čekat na události ve volání jedné metody čekání, jako například WaitOne, WaitAny, nebo WaitAll.WaitHandle.WaitOne()způsobí, že podproces čekat, až bude signalizováno následným tichem jedné události, WaitHandle.WaitAny() zablokuje vlákno, dokud se stanou signalizováno následným tichem uvedena jedna nebo více událostí, a WaitHandle.WaitAll() zablokuje vlákno, dokud všechny uvedené události se stanou signalizováno následným tichem.Událost bude signalizováno následným tichem při jeho Set je volána metoda.

V následujícím příkladu je vytvořen a spuštěn podproces Main funkce.Nový podproces čeká na událost s použitím WaitOne metoda.Podproces je pozastaven, dokud událost stane signalizováno následným tichem primární podproces, který je prováděn Main funkce.Jakmile se událost stane signalizováno následným tichem, pomocné podproces vrací.V tomto případě protože událost slouží pouze pro jeden podproces aktivace buď AutoResetEvent nebo ManualResetEvent třídy nelze používat.

Imports System.Threading

Module Module1
    Dim autoEvent As AutoResetEvent

    Sub DoWork()
        Console.WriteLine("   worker thread started, now waiting on event...")
        autoEvent.WaitOne()
        Console.WriteLine("   worker thread reactivated, now exiting...")
    End Sub

    Sub Main()
        autoEvent = New AutoResetEvent(False)

        Console.WriteLine("main thread starting worker thread...")
        Dim t As New Thread(AddressOf DoWork)
        t.Start()

        Console.WriteLine("main thread sleeping for 1 second...")
        Thread.Sleep(1000)

        Console.WriteLine("main thread signaling worker thread...")
        autoEvent.Set()
    End Sub
End Module
using System;
using System.Threading;

class ThreadingExample
{
    static AutoResetEvent autoEvent;

    static void DoWork()
    {
        Console.WriteLine("   worker thread started, now waiting on event...");
        autoEvent.WaitOne();
        Console.WriteLine("   worker thread reactivated, now exiting...");
    }

    static void Main()
    {
        autoEvent = new AutoResetEvent(false);

        Console.WriteLine("main thread starting worker thread...");
        Thread t = new Thread(DoWork);
        t.Start();

        Console.WriteLine("main thread sleeping for 1 second...");
        Thread.Sleep(1000);

        Console.WriteLine("main thread signaling worker thread...");
        autoEvent.Set();
    }
}

Objekt mutex

A mutex je podobný sledování; zabraňuje souběžné spuštění blok kódu více než jeden podproces najednou.Ve skutečnosti je název "mutex" zkrácená pojmu "vzájemně vylučují." Na rozdíl od monitorů ale objekt mutex lze procesy synchronizace podprocesů.Objekt mutex je zastoupena Mutex třídy.

Při synchronizaci mezi, se nazývá objekt mutex s názvem objektu mutex protože je pro použití v jiné aplikaci, a proto nelze sdílet z globální nebo statické proměnné.Musí mu být přiřazen název tak, aby obě aplikace přístup na stejný objekt mutex.

Přestože objekt mutex pro synchronizaci intra-process vlákno, lze pomocí Monitor je obecně, protože monitory byly navrženy speciálně pro.NET Framework a proto lépe využívat prostředky.Naopak Mutex je třída obálky pro konstrukci Win32.Když je výkonnější než monitor, vyžaduje objekt mutex interop přechodů, které jsou výpočetně náročné než vyžadované Monitor třídy.Příklad použití objekt mutex, viz Mutexy.

Třída šachtu

Můžete použít metody Interlocked třída zabránit problémům, které mohou nastat při pokusu o více podprocesů současně aktualizovat nebo porovnat stejnou hodnotu.Metody této třídy umožňují bezpečně přírůstek, trase, výměnu a porovnat hodnoty z jakékoli vlákno.

ReaderWriter zámky

V některých případech můžete chtít uzamčení prostředku pouze při zápisu dat a povolit více klientů současně číst data v případě, že data nejsou aktualizovány.ReaderWriterLock Třídy vynucuje výhradní přístup k prostředku, zatímco podproces upravuje zdroje, ale umožňuje nevýhradní přístup při čtení prostředku.ReaderWriter zámky jsou užitečnou alternativou k výlučné zámky, které způsobují další podprocesy čekání, i když těchto podprocesů není nutné aktualizovat data.

Zablokování

Synchronizace podprocesů je neocenitelná ve víceprocesových aplikacích, ale vždy existuje nebezpečí vytvoření deadlock, kde vzájemně čekají více podprocesů a aplikace se dodává k zastavení.Zablokování je analogická situaci, ve které automobilů stojíte na čtyřnásobnou stop a ostatní přechod čeká každé osoby.Zabránění zablokování je důležité; klíč je pečlivé plánování.Zablokování situace často lze odhadnout pomocí diagramů s více podprocesy aplikací před zahájením kódování.

Související oddíly

Jak: použití fondu podprocesů (C# a Visual Basic)

Synchronizace přístup ke sdílenému prostředku v prostředí s více podprocesy pomocí aplikace Visual C#.NET

Vytvoření podprocesu pomocí aplikace Visual C#.NET

JAK: Odeslat pracovní položky fondu podprocesů pomocí aplikace Visual C#.NET

Synchronizace přístup ke sdílenému prostředku v prostředí s více podprocesy pomocí aplikace Visual C#.NET

Viz také

Referenční dokumentace

Příkaz SyncLock

Zámek prohlášení (C#-Reference)

Thread

WaitOne

WaitAny

WaitAll

Join

Start

Sleep

Monitor

Mutex

AutoResetEvent

ManualResetEvent

Interlocked

WaitHandle

EventWaitHandle

System.Threading

Set

Koncepty

Aplikace s více podprocesy (C# a Visual Basic)

Mutexy

Monitory

Šachtu operací

AutoResetEvent

Synchronizace dat s více podprocesy

Další zdroje

Provádění CLR asynchronní Model programování

zjednodušené APM s C#

zablokování monitor

Multithreading v součásti

HOW TO: Synchronize Access to a Shared Resource in a Multithreading Environment by Pomocí aplikace Visual C#.NET