Aracılığıyla paylaş


İzlenecek yol: Visual C# ile basit bir çok iş parçacıklı bileşen geliştirme

BackgroundWorker Bileşen değiştirir ve işlevsellik ekler System.Threading ad; Ancak, System.Threading ad alanı korunur geriye dönük uyumluluk ve ileride kullanmak için seçerseniz.Daha fazla bilgi için bkz. BackgroundWorker bileşenlere genel bakış.

Aynı anda birden çok görevi gerçekleştiremez uygulamaları yazabilirsiniz.Olarak adlandırılan bu beceriyi Çoklu kullanım, veya boş iş parçacığı, işlemci yoğun tasarım bileşenleri için güçlü bir araçtır ve kullanıcı girdisi iste.Neden olabilecek bir bileşen örneği kullanımını çoklu kullanım Bordro bilgilerini hesaplayan bir bileşeni olacaktır.Bileşen işlemci yoğun Bordro hesaplamaları başka birinde gerçekleştirilen iken bir veritabanına bir iş parçacığında bir kullanıcı tarafından girilen verileri işleme koyamadı.Bu işlemler ayrı bir iş parçacığı üzerinde çalıştırarak, kullanıcılar ek veri girmeden önce hesaplamaları tamamlamak için bilgisayarı bekleme gerek yoktur.Bu izlenecek yolda, aynı anda birden çok karmaşık hesaplamaları gerçekleştiren basit bir çok iş parçacıklı bileşeni oluşturur.

Projeyi Oluşturma

Uygulamanız, tek bir form ve bir bileşen oluşacaktır.Kullanıcı, değerler ve hesaplamalar başlamak için sinyal bileşenine girecektir.Formu daha sonra bileşeniniz değerleri alırsınız ve etiket denetimleri görüntüler.Bileşen işlemci yoğun hesaplamalar ve form tamamlandığında sinyal.Genel değişkenler kullanıcı arabiriminden alınan deðerleri saklamak için bileşeninizin oluşturacaktır.Bu değişkenlerin değerlerini temel alan hesaplamalar yapmak için bileşenindeki yöntemleri de gerçekleştireceksiniz.

[!NOT]

Genellikle bir işlevi olmasına rağmen bir yöntemi tercih, bir değeri hesaplayan bağımsız iş parçacıkları arasında geçirilemez ve dönen değerleri.Parçacıkları değerlerini sağlamak ve onlardan değerleri almak için çok basit yolu vardır.Bu gösteri genel değişkenler güncelleştirerek kullanıcı arabiriminizi deðerleri döndürecektir ve olayları bir iş parçacığı yürütmeyi tamamladığında, ana program bildirmek için kullanılır.

Gördüğünüz iletişim kutuları ve menü komutları, etkin ayarlarınıza ve ürün sürümüne bağlı olarak Yardım menüsünde açıklanana göre farklılık gösterebilir.Ayarlarınızı değiştirmek için Araçlar menüsünden İçeri ve Dışarı Aktarma Ayarları'nı seçin.Daha fazla bilgi için bkz. Visual Studio ayarları.

Form oluşturmak için

  1. Yeni bir oluşturmak Windows Application proje.

  2. Uygulama adı Calculations ve yeniden adlandırma Form1.cs olarak frmCalculations.cs.Zaman Visual Studio yeniden adlandırmak ister Form1 kod öğesi,'ı Evet.

    Bu formu, uygulamanız için birincil kullanıcı arabirimi olarak hizmet verecektir.

  3. Beş ekleme Label denetler, dört Button kontrol eder ve bir TextBox Formunuza denetim.

  4. Bu denetimlerin özelliklerini aşağıdaki gibi ayarlayın:

    Denetim

    Ad

    Text

    label1

    lblFactorial1

    (boş)

    label2

    lblFactorial2

    (boş)

    label3

    lblAddTwo

    (boş)

    label4

    lblRunLoops

    (boş)

    label5

    lblTotalCalculations

    (boş)

    button1

    btnFactorial1

    Çarpınımı

    button2

    btnFactorial2

    Çarpınımı - 1

    button3

    btnAddTwo

    İki ekleme

    button4

    btnRunLoops

    Bir döngü çalıştırın

    textBox1

    txtValue

    (boş)

Hesap Makinesi bileşen oluşturmak için

  1. Dan Proje menüsünde, select Bileşen ekleme.

  2. Bileşen adı Calculator.

Genel değişkenler için hesap makinesi bileşen eklemek için

  1. Açık Kod Düzenleyicisi'ni için Calculator.

  2. Değerleri geçirmek için kullanılacak ortak değişkenleri oluşturmak için ifadeleri ekleyin frmCalculations her iş parçacığı için.

    Değişken varTotalCalculations hesaplamalar toplam sayısının toplamı bileşeni ve diğer değişkenler tarafından gerçekleştirilen Canlı değerlerini formdan alacak.

    public int varAddTwo; 
    public int varFact1;
    public int varFact2;
    public int varLoopValue;
    public double varTotalCalculations = 0;
    

Hesap Makinesi bileşen yöntemlerini ve olaylarını eklemek için

  1. Bileşeniniz formunuza değerler iletişim kurmak için kullanacağı olayları için temsilciler bildirmek.

    [!NOT]

    Dört olayları bildirmek, ancak iki olayın aynı imzaya sahip olacakları, yalnızca üç temsilci oluşturmanız gerekir.

    Hemen önceki adımda girilen değişken bildirimlerini altında aşağıdaki kodu yazın:

    // This delegate will be invoked with two of your events.
    public delegate void FactorialCompleteHandler(double Factorial, double TotalCalculations);
    public delegate void AddTwoCompleteHandler(int Result, double TotalCalculations);
    public delegate void LoopCompleteHandler(double TotalCalculations, int Counter);
    
  2. Bileþeniniz uygulamanızla iletişim kurmak için kullanacağı olayları bildirmek.Bunu, önceki adımda girdiğiniz kodun hemen altına aşağıdaki kodu ekleyerek yaparsınız.

    public event FactorialCompleteHandler FactorialComplete;
    public event FactorialCompleteHandler FactorialMinusOneComplete;
    public event AddTwoCompleteHandler AddTwoComplete;
    public event LoopCompleteHandler LoopComplete;
    
  3. Hemen önceki adımda yazdığınız kodu altında aşağıdaki kodu yazın:

    // This method will calculate the value of a number minus 1 factorial
    // (varFact2-1!).
    public void FactorialMinusOne()
    {
       double varTotalAsOfNow = 0;
       double varResult = 1;
       // Performs a factorial calculation on varFact2 - 1.
       for (int varX = 1; varX <= varFact2 - 1; varX++)
       {
          varResult *= varX;
          // Increments varTotalCalculations and keeps track of the current 
          // total as of this instant.
          varTotalCalculations += 1;
          varTotalAsOfNow = varTotalCalculations;
       }
       // Signals that the method has completed, and communicates the 
       // result and a value of total calculations performed up to this 
       // point.
       FactorialMinusOneComplete(varResult, varTotalAsOfNow);
    }
    
    // This method will calculate the value of a number factorial.
    // (varFact1!)
    public void Factorial()
    {
       double varResult = 1;
       double varTotalAsOfNow = 0;
       for (int varX = 1; varX <= varFact1; varX++)
       {
          varResult *= varX;
          varTotalCalculations += 1;
          varTotalAsOfNow = varTotalCalculations;
       }
       FactorialComplete(varResult, varTotalAsOfNow);
    }
    
    // This method will add two to a number (varAddTwo+2).
    public void AddTwo()
    {
       double varTotalAsOfNow = 0;  
       int varResult = varAddTwo + 2;
       varTotalCalculations += 1;
       varTotalAsOfNow = varTotalCalculations;
       AddTwoComplete(varResult, varTotalAsOfNow);
    }
    
    // This method will run a loop with a nested loop varLoopValue times.
    public void RunALoop()
    {
       int varX;
       double varTotalAsOfNow = 0;
       for (varX = 1; varX <= varLoopValue; varX++)
       {
        // This nested loop is added solely for the purpose of slowing down
        // the program and creating a processor-intensive application.
          for (int varY = 1; varY <= 500; varY++)
          {
             varTotalCalculations += 1;
             varTotalAsOfNow = varTotalCalculations;
          }
       }
       LoopComplete(varTotalAsOfNow, varLoopValue);
    }
    

Bileşen için kullanıcı girişi aktarılıyor

Sonraki adım kodu eklemektir frmCalculations kullanıcıdan girdi almak ve aktarmak ve birinden diğerine değerleri almak için Calculator bileşeni.

FrmCalculations için ön uç işlevselliğini uygulamak için

  1. Açık frmCalculations , Kod Düzenleyicisi'ni.

  2. Bulun public partial class frmCalculations ifadesi.Hemen altındaki { türü:

    Calculator Calculator1;
    
  3. Kurucusunu bulun.Hemen önce }, aşağıdaki satırı ekleyin:

    // Creates a new instance of Calculator.
    Calculator1 = new Calculator();
    
  4. Tasarımcısı'nda her bir denetimin kodu anahat oluşturmak için her düğmesini Click olay işleyicileri ve işleyicileri oluşturmak için kod ekleyin.

    Tamamlandığında, sizin Click olay işleyicisini aşağıdaki benzer:

    // Passes the value typed in the txtValue to Calculator.varFact1.
    private void btnFactorial1_Click(object sender, System.EventArgs e)
    {
       Calculator1.varFact1 = int.Parse(txtValue.Text);
       // Disables the btnFactorial1 until this calculation is complete.
       btnFactorial1.Enabled = false;
       Calculator1.Factorial();
    }
    
    private void btnFactorial2_Click(object sender, System.EventArgs e)
    {
       Calculator1.varFact2 = int.Parse(txtValue.Text);
       btnFactorial2.Enabled = false;
       Calculator1.FactorialMinusOne();
    }
    private void btnAddTwo_Click(object sender, System.EventArgs e)
    {
       Calculator1.varAddTwo = int.Parse(txtValue.Text);
       btnAddTwo.Enabled = false;
       Calculator1.AddTwo();
    }
    private void btnRunLoops_Click(object sender, System.EventArgs e)
    {
       Calculator1.varLoopValue = int.Parse(txtValue.Text);
       btnRunLoops.Enabled = false;
       // Lets the user know that a loop is running
       lblRunLoops.Text = "Looping";
       Calculator1.RunALoop();
    }
    
  5. Önceki adımda eklediğiniz koddan sonra formunuzu alma olayları işlemek için aşağıdakini yazın Calculator1:

    private void FactorialHandler(double Value, double Calculations)
    // Displays the returned value in the appropriate label.
    {
       lblFactorial1.Text = Value.ToString();
       // Re-enables the button so it can be used again.
       btnFactorial1.Enabled = true;
       // Updates the label that displays the total calculations performed
       lblTotalCalculations.Text = "TotalCalculations are " + 
          Calculations.ToString();
    }
    
    private void FactorialMinusHandler(double Value, double Calculations)
    {
       lblFactorial2.Text = Value.ToString();
       btnFactorial2.Enabled = true;
       lblTotalCalculations.Text = "TotalCalculations are " + 
          Calculations.ToString();
    }
    
    private void AddTwoHandler(int Value, double Calculations)
    {
       lblAddTwo.Text = Value.ToString();
       btnAddTwo.Enabled = true;
       lblTotalCalculations.Text = "TotalCalculations are " +
          Calculations.ToString();
    }
    
    private void LoopDoneHandler(double Calculations, int Count)
    {
       btnRunLoops.Enabled = true;
       lblRunLoops.Text = Count.ToString();
       lblTotalCalculations.Text = "TotalCalculations are " +
          Calculations.ToString();
    }
    
  6. Oluşturucusunun içinde frmCalculations, hemen önce aşağıdaki kodu ekleyip } formunuzu almak özel olayları işlemek için Calculator1.

    Calculator1.FactorialComplete += new
       Calculator.FactorialCompleteHandler(this.FactorialHandler);
    Calculator1.FactorialMinusOneComplete += new
       Calculator.FactorialCompleteHandler(this.FactorialMinusHandler);
    Calculator1.AddTwoComplete += new
       Calculator.AddTwoCompleteHandler(this.AddTwoHandler);
    Calculator1.LoopComplete += new
       Calculator.LoopCompleteHandler(this.LoopDoneHandler);
    

Uygulamanızı test etme

Şimdi bir bileşeni çeşitli karmaşık hesaplamalar gerçekleştirebilir ve biçimi içeren bir proje oluşturduk.Çoklu kullanım yeteneği henüz kaydettirmeyen olsa da, devam etmeden önce işlevselliğini doğrulamak için projenizi sınayacak.

Projenizi sınamak için

  1. Dan Debug menüsünden seçin Start Debugging komutunu.

    Uygulama başlar ve frmCalculations görünür.

  2. Metin kutusuna 4, etiketli düğmesini tıklatıp Eklemek iki.

    "6" Rakamı altındaki etiket görüntüleneceğini ve "Toplam hesaplamaları are 1" görüntüleneceğini lblTotalCalculations.

  3. Şimdi etiketli düğmeyi çarpınımı - 1.

    "6" Rakamı düğmesini görüntülenmesi gerektiğini ve lblTotalCalculations şimdi "toplam hesaplamaları olan 4."

  4. Metin kutusu değerini değiştirmek 20, etiketli düğmesini tıklatıp çarpınımı.

    Bunun "2.43290200817664E + 18" numarası görüntülenir ve lblTotalCalculations şimdi "Toplam hesaplamaları var. 24" okur

  5. Metin kutusu değerini değiştirmek 50000'den, etiketli düğmeyi tıklatıp ardından Çalışacak bir döngü.

    Bu düğmeyi yeniden etkinleştirildi önce küçük, ancak dikkat çekici bir aralığı olduğunu unutmayın.Bu düğme altında etiket "50000'den" okumalısınız ve görüntülenen toplam hesaplamaları olan "25000024"

  6. Metin kutusu değerini değiştirmek 5000000 ve etiketli düğmeyi tıklatın Çalışacak bir döngü, hemen etiketli düğmeyi tıklatın Eklemek iki.Yeniden tıklatın.

    Düğme yanıt vermiyor, ne de herhangi bir denetimi form üzerinde döngüler tamamlanıncaya kadar yanıt verir.

    Yalnızca tek bir iş parçacığı yürütme programınız çalışıyorsa, yukarıdaki örnekteki gibi işlemci yoğun hesaplamalar hesaplamaları tamamlayıncaya kadar programı tedariği birbirine bağlamanın eğilimi vardır.Sonraki bölümde, birden çok iş parçacığı aynı anda çalışacak şekilde uygulamanıza çoklu kullanım yeteneği ekleyeceksiniz.

Çoklu kullanım özelliği ekleme

Önceki örnekte, yalnızca tek bir iş parçacığı yürütme çalıştırılan uygulamaların sınırlamalarını gösterilmektedir.Sonraki bölümde kullanacağınız Thread birden çok iş parçacığı yürütme, bileşen eklemek için sınıf.

İş parçacığı altyordamını eklemek için

  1. Açık Calculator.cs , Kod Düzenleyicisi'ni.

  2. Kod üst, sınıf bildirisinin bulun ve hemen altındaki {, aşağıdaki komutu yazın:

    // Declares the variables you will use to hold your thread objects.
    public System.Threading.Thread FactorialThread; 
    public System.Threading.Thread FactorialMinusOneThread;  
    public System.Threading.Thread AddTwoThread; 
    public System.Threading.Thread LoopThread;
    
  3. Hemen altındaki kodu sınıf bildirisinin önce aşağıdaki yöntemi ekleyin:

    public void ChooseThreads(int threadNumber)
    {
    // Determines which thread to start based on the value it receives.
    switch(threadNumber)
       {
          case 1:
             // Sets the thread using the AddressOf the subroutine where
             // the thread will start.
             FactorialThread = new System.Threading.Thread(new
                System.Threading.ThreadStart(this.Factorial));
             // Starts the thread.
             FactorialThread.Start();
             break;
          case 2:
             FactorialMinusOneThread = new
                System.Threading.Thread(new
                   System.Threading.ThreadStart(this.FactorialMinusOne));
             FactorialMinusOneThread.Start();
             break;
          case 3:
             AddTwoThread = new System.Threading.Thread(new
                 System.Threading.ThreadStart(this.AddTwo));
             AddTwoThread.Start();
             break;
          case 4:
             LoopThread = new System.Threading.Thread(new
                System.Threading.ThreadStart(this.RunALoop));
             LoopThread.Start();
             break;
       }
    }
    

    Zaman bir Thread olan örneği, şeklindeki bir bağımsız değişken gerektiren bir ThreadStart.ThreadStart Yöntemi adresine işaret eden burada başlamak için iş parçacığı, bir temsilcidir.A ThreadStart parametreleri veya geçişi değerleri alınamıyor ve bu nedenle yalnızca gösterebilen bir void yöntemi.ChooseThreads Yalnızca uygulanan yöntem onu çağıran programdan bir değer alması ve başlatmak için uygun iş parçacığı belirlemek için bu değeri kullanın.

FrmCalculations için uygun kod eklemek için

  1. Açık frmCalculations.cs , dosya Kod Düzenleyicisi'ni, sonra bulmak private void btnFactorial1_Click.

    1. Çağıran satırı altyordamýndaki Calculator1.Factorial1 doğrudan gösterildii gibi yöntemi:

      // Calculator1.Factorial()
      
    2. Aramak için aşağıdaki satırı ekleyin Calculator1.ChooseThreads yöntemi:

      // Passes the value 1 to Calculator1, thus directing it to start the 
      // correct thread.
      Calculator1.ChooseThreads(1);
      
  2. Benzer diğer değişiklikler button_click yöntemleri.

    [!NOT]

    İçin uygun değer içerecek şekilde emin olmanız Threads bağımsız değişkeni.

    Bitirdiğinizde, kod aşağıdaki gibi görünmelidir:

    private void btnFactorial1_Click(object sender, System.EventArgs e)
    // Passes the value typed in the txtValue to Calculator.varFact1
    {
       Calculator1.varFact1 = int.Parse(txtValue.Text);
       // Disables the btnFactorial1 until this calculation is complete
       btnFactorial1.Enabled = false;
       // Calculator1.Factorial();
       Calculator1.ChooseThreads(1);
    }
    
    private void btnFactorial2_Click(object sender, System.EventArgs e)
    {
       Calculator1.varFact2 = int.Parse(txtValue.Text); 
       btnFactorial2.Enabled = false;         
       // Calculator1.FactorialMinusOne();
       Calculator1.ChooseThreads(2);
    }
    private void btnAddTwo_Click(object sender, System.EventArgs e)
    {
       Calculator1.varAddTwo = int.Parse(txtValue.Text);
       btnAddTwo.Enabled = false;
       // Calculator1.AddTwo();
       Calculator1.ChooseThreads(3);
    }
    
    private void btnRunLoops_Click(object sender, System.EventArgs e)
    {
       Calculator1.varLoopValue = int.Parse(txtValue.Text);
       btnRunLoops.Enabled = false;
       // Lets the user know that a loop is running
       lblRunLoops.Text = "Looping";
       // Calculator1.RunALoop();
       Calculator1.ChooseThreads(4);
    }
    

Denetimleri çağrıları sıralaması

Şimdi, formu ekranda güncelleme salayacaktır.Denetimler her zaman ana yürütme iş parçacığı tarafından sahipliğinde olduğundan herhangi bir çağrısından bir denetime bağımlı iş parçacığının gerektiren bir sıralama çağırın.Sıralama, iş parçacığı sınırlarında bir çağrı taşıma işlemidir ve kaynaklar oldukça maliyetlidir.Oluşur ve aramalarınız iş parçacığı için güvenli bir biçimde işlediğinden emin olmak için gereken sıralaması miktarını en aza indirmek için kullanacağınız Control.BeginInvoke ana iş parçacığında yürütme, böylece gerçekleşmelidir çapraz iş parçacığı sınırı sıralaması miktarını en aza indirme yöntemlerini çağırmak için yöntem.Bu tür bir çağrı denetimlerini işleme yöntemi çağrılırken gereklidir.Ayrıntılar için bkz. Nasıl yapılır: iş parçacığı denetimlerden işlemek.

Denetim yürütmesini yordamları oluşturmak için

  1. Kod Düzenleyicisi'ni açma frmCalculations.Tanımlamalar bölümüne aşağıdaki kodu ekleyin:

    public delegate void FHandler(double Value, double Calculations);
    public delegate void A2Handler(int Value, double Calculations);
    public delegate void LDHandler(double Calculations, int Count);
    

    Invokeve BeginInvoke uygun yönteme bir bağımsız değişken olarak bir temsilci gerektirir.Bu satırlar tarafından kullanılan imzalar temsilcinin bildirmek BeginInvoke uygun yöntemleri çağırmak için.

  2. Aşağıdaki boş yöntemler kodunuzu ekleyin.

    public void FactHandler(double Value, double Calculations)
    {
    }
    public void Fact1Handler(double Value, double Calculations)
    {
    }
    public void Add2Handler(int Value, double Calculations)
    {
    }
    public void LDoneHandler(double Calculations, int Count)
    {
    }
    
  3. Dan düzenleme kullan menüsünden Kes ve yapıştırın yönteminden tüm kodu kesmek için FactorialHandler ve içine yapıştırın FactHandler.

  4. Repeat the previous step for FactorialMinusHandler and Fact1Handler, AddTwoHandler and Add2Handler, and LoopDoneHandler and LDoneHandler.

    Bitirdiğinizde, kod içinde kalan olmalıdır FactorialHandler, Factorial1Handler, AddTwoHandler, ve LoopDoneHandlerve bunlar içermek için kullanılan taşınır uygun yeni yöntemler için kod.

  5. Call BeginInvoke zaman uyumsuz olarak yöntemlerini çağırmak için yöntem.Arayabileceğiniz BeginInvoke da formunuzu (this) veya herhangi bir form üzerindeki denetimleri.

    Tamamlandığında, kodunuzun aşağıdakine benzer görünmelidir:

    protected void FactorialHandler(double Value, double Calculations)
    {
       // BeginInvoke causes asynchronous execution to begin at the address
       // specified by the delegate. Simply put, it transfers execution of 
       // this method back to the main thread. Any parameters required by 
       // the method contained at the delegate are wrapped in an object and 
       // passed. 
       this.BeginInvoke(new FHandler(FactHandler), new Object[]
          {Value, Calculations});
    }
    protected void FactorialMinusHandler(double Value, double Calculations)
    {
       this.BeginInvoke(new FHandler(Fact1Handler), new Object []
          {Value, Calculations});
    }
    
    protected void AddTwoHandler(int Value, double Calculations)
    {
       this.BeginInvoke(new A2Handler(Add2Handler), new Object[]
          {Value, Calculations});
    }
    
    protected void LoopDoneHandler(double Calculations, int Count)
    {
       this.BeginInvoke(new LDHandler(LDoneHandler), new Object[]
          {Calculations, Count});
    }
    

    Olay işleyicisi basitçe sonraki yöntemine yapılan bir çağrı yapma gibi olsa da görünebilir.Olay işleyicisi işlemi ana iş parçacığı üzerinde çağrılacak yöntemi aslında neden oluyor.Bu yaklaşım, iş parçacığı sınırlarında çağrılarda kaydeder ve verimli ve kilitlenmesine neden olan Korku olmadan çalıştırmak, çok iş parçacıklı uygulamalar sağlar.Çok iş parçacıklı ortamda denetimleri ile çalışma hakkında daha fazla bilgi için bkz: Nasıl yapılır: iş parçacığı denetimlerden işlemek.

  6. Çalışmanızı kaydedin.

  7. Seçerek çözümünüzü deneyin Start Debugging komutunu karşı Debug menüsü.

    1. Type 10000000 tıklatın ve metin kutusu içindeki Çalışacak bir döngü.

      Bu düğmenin altındaki etikette "Döngü" görüntülenir.Bu döngü, önemli ölçüde çalıştırılacak zaman almanız gerekir.Çok erken tamamlarsa, sayının boyutuna uygun şekilde ayarlayın.

    2. Art arda hızlı biçimde, halen etkin olan tüm üç düğmelerini tıklatın.Tüm düğmeleri iletilerinizi ºu adrese yanıt bulacaksınız.Altındaki etikette Eklemek iki bir sonucu görüntülemek için ilk olmalıdır.Sonuçlar daha sonra etiketlerde Faktöriyel düğmeleri altında görüntülenir.10,000,000 Çarpınımı tarafından döndürülen sayı bir çift duyarlıklı değişken içeren çok büyük olduğu gibi bu sonuçlar sonsuza kadar değerlendirin.Son olarak, ek bir gecikmeden sonra sonuçları altında döndürülen Çalışacak bir döngü düğme.

      Yalnızca gözlenen gibi dört ayrı bir kümesi hesaplamaları aynı anda dört ayrı iş parçacıkları gerçekleştirilmiştir.Kullanıcı arabirimi giriş tepki olarak kalır ve tamamlanan her iş parçacığı sonra sonuç döndürülmedi.

Kendi iş parçacığı koordine

Çok iş parçacıklı uygulamalarda deneyimli kullanıcı koduyla yazılan ince bir kusur düşünebilir.Hesaplamayı gerçekleştirmeden Her yöntemdeki kod satırları geri çağırmak Calculator:

varTotalCalculations += 1;
varTotalAsOfNow = varTotalCalculations;

Bu iki kod satırı ortak deðiþkenini artýrmak varTotalCalculations ve yerel değişken varTotalAsOfNow için bu değeri.Bu değer daha sonra döndürülen frmCalculations ve bir label denetimi görüntülenir.Ancak, doğru değer verdi?Yalnızca tek bir yürütme iş parçacığı çalışıyor, açıkça yanıttır Evet.Ancak, birden çok iş parçacığı çalıştırıyorsanız, yanıt daha belirsiz hale gelir.Her iş parçacığı deðiþkenini artýrmak gönderebilen varTotalCalculations.Bu değişken artırır, bir iş parçacığının sonra mümkün olduğu halde önce onu kopyalar değeri varTotalAsOfNow, başka bir iş parçacığı bu değişkenin değerini artırma ile değiştirecek.Bu her iş parçacığı tutarsız sonuçlar aslında raporlama olasılık yol açar.Visual C#sağlayan LOCK deyimi (C# Reference) her iş parçacığı her zaman doğru sonuç verir emin olmak için iş parçacıkları eşitlemeye izin vermek için.Sözdizimi lock aşağıdaki gibidir:

lock(AnObject)
{
   // Insert code that affects the object.
   // Insert more code that affects the object.
   // Insert more code that affects the object.
// Release the lock.
}

Zaman lock blok girilir, söz konusu nesne üzerinde özel kilit belirtilen iş parçacığı sahip olana kadar üzerinde belirtilen deyim yürütme engellendi.Yukarıda gösterilen örnekte, yürütme engellendi AnObject.lockbir değer yerine, bir başvuru veren bir nesne ile kullanılması gerekir.Yürütme sonra bloğu hiçbir kesinti olmadan devam edebilirsiniz.Bir birim olarak execute deyimleri kümesini olmasını söyledi Atomik.Zaman } olan karşılaştı, ve ifade serbest iş parçacığı normal olarak devam etmek için izin verilir.

Lock deyiminin uygulamanıza eklemek için

  1. Açık Calculator.cs , Kod Düzenleyicisi'ni.

  2. Her bir örneği aşağıdaki kodu bulun:

    varTotalCalculations += 1;
    varTotalAsOfNow = varTotalCalculations;
    

    Bu kod, hesaplama yöntemi her birinde dört örneklerini olması gerekir.

  3. Bu kodu aşağıdaki gibi değiştirin:

    lock(this)
    {
       varTotalCalculations += 1;
       varTotalAsOfNow = varTotalCalculations;
    }
    
  4. Çalışmanızı kaydedin ve önceki örnekte olduğu gibi test edin.

    Programınızın performansını hafif bir etkisi olduğunu fark edebilirsiniz.Bileþeniniz üzerinde özel kilit alındığında yürütme iş parçacığı durdurulur olmasıdır.Doğruluk sağlar, ancak bu yaklaşım bazı birden çok iş parçacığı performans avantajı impedes.Dikkatle kilitleme iş parçacığı gereğini göz önünde bulundurun ve bunları yalnızca kesinlikle gerekli olduğunda uygulamak gerekir.

Ayrıca bkz.

Görevler

Nasıl yapılır: birden çok iş parçacığı yürütme eşgüdümlemek

İzlenecek yol: Visual Basic ile basit bir çok iş parçacıklı bileşen geliştirme

Başvuru

BackgroundWorker

Kavramlar

Olay tabanlı zaman uyumsuz desen genel bakış

Diğer Kaynaklar

Bileşenler ile programlama

Bileşen programlama izlenecek yollar

Çoklu kullanım bileşenleri