Πώς μπορείτε να συγχρονίσετε την πρόσβαση σε έναν κοινόχρηστο πόρο σε ένα περιβάλλον πολλαπλών νημάτων χρησιμοποιώντας το Visual C#

Σύνοψη

Μπορείτε να εκτελέσετε πολλές εργασίες σε Microsoft Visual C# εφαρμογές ταυτόχρονα με τη χρήση πολλαπλών νημάτων. Πολλαπλών νημάτων μπορεί να ξεκινήσει διαφορετικών νημάτων για να ολοκληρώσετε διάφορες εργασίες ταυτόχρονα. Πολλαπλών νημάτων επίσης βελτιώνει τις επιδόσεις και την ανταπόκριση των εφαρμογών σας.

Επειδή πολλά νήματα να αποκτήσετε πρόσβαση σε έναν πόρο την ίδια στιγμή, μπορεί να θέλετε να συγχρονίσετε μεμονωμένα νήματα με άλλα τμήματα του προγράμματος. Αυτό το άρθρο περιγράφει ορισμένα κοινά σενάρια με προγραμματισμό πολλαπλών νημάτων και εξηγεί τον τρόπο για να συγχρονίσετε την πρόσβαση σε έναν κοινόχρηστο πόρο από τα πολλά νήματα.

Επιστροφή στην κορυφή

Βοήθεια για την προστασία σας καθολικά δεδομένα σε λειτουργικές μονάδες σε ένα περιβάλλον πολλαπλών νημάτων

Τα δημόσια πεδία μεθόδους είναι δυνατή η πρόσβαση σε όλα τα νήματα στην εφαρμογή σας. Για να συγχρονίσετε την πρόσβαση στα δημόσια πεδία, μπορείτε να χρησιμοποιήσετε ιδιότητα αντί για το πεδίο και να χρησιμοποιήσετε ένα αντικείμενο ReaderWriterLock για να ελέγξετε την πρόσβαση. Για να το κάνετε αυτό, ακολουθήστε τα εξής βήματα:
  1. Ξεκινήστε το Microsoft Visual Studio.
  2. Στο μενού αρχείο , επιλέξτε Δημιουργίακαι, στη συνέχεια, κάντε κλικ στο έργο.
  3. Κάντε κλικ στο κουμπί
    Visual C# έργα στην περιοχή Τύπους έργων, και στη συνέχεια κάντε κλικ στο κουμπί Εφαρμογή κονσόλας στην περιοχή
    Πρότυπα.

    Σημείωση Στο Visual Studio 2005 ή στο Visual Studio 2008, κάντε κλικ στο κουμπί Visual C# στην περιοχή Τύπους έργων, και στη συνέχεια κάντε κλικ στο κουμπί Εφαρμογή κονσόλας στην περιοχή
    Πρότυπα.
  4. Στο πλαίσιο κειμένου " όνομα ", πληκτρολογήστε
    MultiThreadApplicationκαι, στη συνέχεια, κάντε κλικ στο κουμπί
    OK.
  5. Αντικαταστήστε τον υπάρχοντα κωδικό με τον ακόλουθο κώδικα στο Class1.cs.

    Σημείωση Στο Visual Studio 2005 και στο Visual Studio 2008, το προεπιλεγμένο αρχείο είναι Program.cs.
    using System;using System.Threading;

    namespace MultiThreadApplication
    {
    class Class1
    {
    private ReaderWriterLock rwl = new ReaderWriterLock();
    private long myNumber;
    public long Number // the Number property
    {
    get
    {
    //Acquire a read lock on the resource.
    rwl.AcquireReaderLock(Timeout.Infinite);
    try
    {
    Console.WriteLine("Thread:{0} starts getting the Number", Thread.CurrentThread.GetHashCode());
    Thread.Sleep(50);
    Console.WriteLine("Thread:{0} got the Number", Thread.CurrentThread.GetHashCode());

    }
    finally
    {
    //Release the lock.
    rwl.ReleaseReaderLock();
    }
    return myNumber;
    }
    set
    {
    //Acquire a write lock on the resource.
    rwl.AcquireWriterLock(Timeout.Infinite);
    try
    {
    Console.WriteLine("Thread: {0} start writing the Number", Thread.CurrentThread.GetHashCode());
    Thread.Sleep(50);
    myNumber = value;
    Console.WriteLine("Thread: {0} written the Number", Thread.CurrentThread.GetHashCode());
    }
    finally
    {
    //Release the lock.
    rwl.ReleaseWriterLock();
    }
    }
    }

    [STAThread]
    static void Main(string[] args)
    {
    Thread []threadArray = new Thread[20];
    int threadNum;


    Class1 Myclass = new Class1();
    ThreadStart myThreadStart = new ThreadStart(Myclass.AccessGlobalResource);

    //Create 20 threads.
    for( threadNum = 0; threadNum < 20; threadNum++)
    {
    threadArray[threadNum] = new Thread(myThreadStart);
    }

    //Start the threads.
    for( threadNum = 0; threadNum < 20; threadNum++)
    {
    threadArray[threadNum].Start();
    }

    //Wait until all the thread spawn out finish.
    for( threadNum = 0; threadNum < 20; threadNum++)
    threadArray[threadNum].Join();

    Console.WriteLine("All operations have completed. Press enter to exit");
    Console.ReadLine();
    }

    public void AccessGlobalResource()
    {
    Random rnd = new Random();
    long theNumber;

    if (rnd.Next() % 2 != 0)
    theNumber = Number;
    else
    {
    theNumber = rnd.Next();
    Number = theNumber;
    }

    }
    }
    }

  6. Δημιουργήστε το έργο και, στη συνέχεια, εκτελέστε την εφαρμογή.
Επιστροφή στην κορυφή

Να εξασφαλίσετε την κλάση σας ασφαλές για τα νήματα

Πολλά νήματα ενδέχεται να προσπαθήσει να αποκτήσει πρόσβαση σε ένα αντικείμενο την ίδια στιγμή. Όταν περισσότερα από ένα νήματα ανταγωνίζεται για πρόσβαση σε ένα αντικείμενο την ίδια στιγμή, ορισμένα νήματα ενδέχεται να εμφανιστεί μια μη έγκυρη κατάσταση, εάν κάποιο άλλο νήμα τροποποιεί τον πόρο, την ίδια στιγμή. Για παράδειγμα, εάν ένα νήμα διαβάζει το πεδίο του αντικειμένου, ενώ το άλλο νήμα τροποποιώντας το πεδίο, το πρώτο νήμα ενδέχεται να εμφανιστεί μια μη έγκυρη κατάσταση του πεδίου. Η κατάσταση αυτή ονομάζεται μια κατάσταση κούρσας.

Για να αποφύγετε αυτήν την περίπτωση, μπορείτε να βοηθήσετε στην προστασία κρίσιμων ενοτήτων του κώδικά σας από καταστάσεις ανταγωνισμού χρησιμοποιώντας κλειδώματα. Κλείδωμα, που αντιπροσωπεύεται από το Visual C# λέξη-κλειδί κλείδωμα δήλωση, επιτρέπει σε ένα νήμα εκτέλεσης για να αποκτήσετε δικαιώματα εκτέλεσης για αποκλειστική χρήση σε ένα αντικείμενο. Τα παρακάτω βήματα παράδειγμα δείχνουν κλειδωμάτων:
  1. Ανοίξτε το Visual Studio.
  2. Στο μενού αρχείο , επιλέξτε Δημιουργίακαι, στη συνέχεια, κάντε κλικ στο έργο.
  3. Κάντε κλικ στο κουμπί
    Visual C# έργα στην περιοχή Τύπους έργων, και στη συνέχεια κάντε κλικ στο κουμπί Εφαρμογή κονσόλας στην περιοχή
    Πρότυπα.

    Σημείωση Στο Visual Studio 2005 ή στο Visual Studio 2008, κάντε κλικ στο κουμπί Visual C# στην περιοχή Τύπους έργων, και στη συνέχεια κάντε κλικ στο κουμπί Εφαρμογή κονσόλας στην περιοχή
    Πρότυπα.
  4. Στο πλαίσιο κειμένου " όνομα ", πληκτρολογήστε
    MultiThreadLockApplicationκαι, στη συνέχεια, κάντε κλικ στο κουμπί
    OK.
  5. Αντικαταστήστε τον υπάρχοντα κωδικό με τον ακόλουθο κώδικα στο Class1.cs:
    using System;using System.Threading;

    namespace MultiThreadLockApplication
    {
    class Student
    {
    private static string myTeacherName = "Bill";
    private string myName = "Grace";
    private static object somePrivateStaticObject = new Object();

    public static string TeacherName
    {
    get
    {
    string theName;

    // Synchronize access to the shared member.
    lock(somePrivateStaticObject)
    {
    Console.WriteLine("Thread {0} starts to get the teacher's name",Thread.CurrentThread.GetHashCode());
    theName = myTeacherName;

    // Wait for 0.3 second.
    Thread.Sleep(300);
    Console.WriteLine("Thread {0} finished to get the teacher's name:{1}.", Thread.CurrentThread.GetHashCode(), theName);
    }
    return theName;
    }

    set
    {
    lock(somePrivateStaticObject)
    {
    Console.WriteLine("Thread {0} starts to set the teacher's name.", Thread.CurrentThread.GetHashCode());
    myTeacherName = value;

    // Wait for 0.3 second.
    Thread.Sleep(300);
    Console.WriteLine("Thread {0} finished to set the teacher's name:{1}.", Thread.CurrentThread.GetHashCode(), value);
    }
    }
    }

    public string GetName()
    {
    string theName;
    lock(this)
    {
    Console.WriteLine("Thread {0} starts to get the student's name.", Thread.CurrentThread.GetHashCode());
    theName = myName;

    // Wait for 0.3 second.
    Thread.Sleep(300);
    Console.WriteLine("Thread {0} finished to get the student's name:{1}", Thread.CurrentThread.GetHashCode(), theName);
    return theName;
    }
    }

    public string SetName(string NewName)
    {
    string theOldName;
    lock(this)
    {
    Console.WriteLine("Thread {0} starts to set the student's name.", Thread.CurrentThread.GetHashCode());
    theOldName = myName;
    myName = NewName;

    // Wait for 0.3 second.
    Thread.Sleep(300);
    Console.WriteLine("Thread {0} finished to set the student's name:{1}", Thread.CurrentThread.GetHashCode(), NewName);
    }
    return theOldName;
    }
    }

    class Class1
    {
    public static int WorkItemNum = 20;
    public static AutoResetEvent Done = new AutoResetEvent(false);

    public static void AccessClassResource(object state)
    {
    Random rnd = new Random();
    string theName;
    Student AStudent = (Student) state;

    if( (rnd.Next() %2) != 0)
    {
    if( (rnd.Next() %2) != 0)
    {
    switch (rnd.Next() %3 )
    {
    case 0:
    Student.TeacherName = "Tom";
    break;
    case 1:
    Student.TeacherName = "Mike";
    break;
    case 2:
    Student.TeacherName = "John";
    break;
    }
    }
    else
    {
    theName = Student.TeacherName;
    }
    }
    else
    {
    if( (rnd.Next() %2) != 0)
    {
    switch (rnd.Next() %3 )
    {
    case 0:
    AStudent.SetName("Janet");
    break;
    case 1:
    AStudent.SetName("David");
    break;
    case 2:
    AStudent.SetName("Ben");
    break;
    }
    }
    else
    {
    theName = AStudent.GetName();
    }
    }

    if(Interlocked.Decrement( ref WorkItemNum) == 0)
    {
    Done.Set();
    }
    }

    [STAThread]
    static void Main(string[] args)
    {
    int threadNum;
    Student AStudent = new Student();

    // Queue up 20 work items in the ThreadPool.
    for (threadNum = 0 ; threadNum <= WorkItemNum -1 ; threadNum++)
    {
    ThreadPool.QueueUserWorkItem(new WaitCallback(AccessClassResource),AStudent);
    }

    Done.WaitOne();
    Console.WriteLine("All operations have completed. Press enter to exit");
    Console.ReadLine();
    }
    }
    }
  6. Δημιουργήστε το έργο και, στη συνέχεια, εκτελέστε την εφαρμογή.
Επιστροφή στην κορυφή

Αναφορές

Για περισσότερες πληροφορίες, ανατρέξτε στις ακόλουθες τοποθεσίες της Microsoft Developer Network (MSDN) στο Web:Επιστροφή στην κορυφή
Ιδιότητες

Αναγνωριστικό άρθρου: 816161 - Τελευταία αναθεώρηση: 17 Ιαν 2017 - Αναθεώρηση: 1

Σχόλια