Denetimlere iş parçacığı güvenli çağrılar yapma (Windows Forms .NET)
Çoklu iş parçacığı kullanımı, Windows Forms uygulamalarının performansını artırabilir, ancak Windows Forms denetimlerine erişim doğal olarak iş parçacığı açısından güvenli değildir. Çoklu iş parçacığı kullanımı kodunuzu ciddi ve karmaşık hatalara maruz bırakabilir. Denetimi yönlendiren iki veya daha fazla iş parçacığı, denetimi tutarsız bir duruma zorlayabilir ve yarış koşullarına, kilitlenmelere ve donmalara veya kilitlenmelere yol açabilir. Uygulamanızda çok iş parçacığı kullanımı uygularsanız, iş parçacığı arası denetimleri iş parçacığı güvenli bir şekilde çağırdığınızdan emin olun. Daha fazla bilgi için bkz . Yönetilen iş parçacığı oluşturma en iyi yöntemleri.
Önemli
.NET 7 ve .NET 6 için Masaüstü Kılavuzu belgeleri yapım aşamasındadır.
Bu denetimi oluşturmayan bir iş parçacığından Windows Forms denetimini güvenli bir şekilde çağırmanın iki yolu vardır. System.Windows.Forms.Control.Invoke Ana iş parçacığında oluşturulan ve ardından denetimi çağıran bir temsilciyi çağırmak için yöntemini kullanın. Alternatif olarak, arka plan iş parçacığında yapılan işleri sonuçlar üzerinde raporlamadan ayırmak için olay temelli bir model kullanan bir System.ComponentModel.BackgroundWorkeruygulayabilirsiniz.
Güvenli olmayan iş parçacıkları arası çağrılar
Doğrudan oluşturmamış bir iş parçacığından bir denetimi çağırmak güvenli değildir. Aşağıdaki kod parçacığı, denetime yönelik güvenli olmayan bir çağrıyı System.Windows.Forms.TextBox gösterir. Olay işleyicisi Button1_Click
, ana iş parçacığının özelliğini doğrudan ayarlayan yeni WriteTextUnsafe
bir iş parçacığı TextBox.Text oluşturur.
private void button1_Click(object sender, EventArgs e)
{
var thread2 = new System.Threading.Thread(WriteTextUnsafe);
thread2.Start();
}
private void WriteTextUnsafe() =>
textBox1.Text = "This text was set unsafely.";
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim thread2 As New System.Threading.Thread(AddressOf WriteTextUnsafe)
thread2.Start()
End Sub
Private Sub WriteTextUnsafe()
TextBox1.Text = "This text was set unsafely."
End Sub
Visual Studio hata ayıklayıcısı, iş parçacıkları arası işlem geçerli değil iletisiyle bir InvalidOperationException oluşturarak bu güvenli olmayan iş parçacığı çağrılarını algılar. Denetim, oluşturulduğu iş parçacığı dışında bir iş parçacığından erişilir. Her InvalidOperationException zaman Visual Studio hata ayıklaması sırasında güvenli olmayan iş parçacıkları arası çağrılar için gerçekleşir ve uygulama çalışma zamanında gerçekleşebilir. Sorunu düzeltmeniz gerekir, ancak özelliğini false
olarak ayarlayarak Control.CheckForIllegalCrossThreadCalls özel durumu devre dışı bırakabilirsiniz.
İş parçacıkları arası çağrıları Kasa
Aşağıdaki kod örnekleri, oluşturmamış bir iş parçacığından Windows Forms denetimini güvenli bir şekilde çağırmanın iki yolunu gösterir:
- Denetimi System.Windows.Forms.Control.Invoke çağırmak için ana iş parçacığından bir temsilci çağıran yöntemi.
- System.ComponentModel.BackgroundWorker Olay temelli model sunan bir bileşen.
Her iki örnekte de arka plan iş parçacığı, bu iş parçacığında yapılan işlerin benzetimini yapmak için bir saniye boyunca uykudadır.
Örnek: Invoke yöntemini kullanma
Aşağıdaki örnek, Windows Forms denetimine iş parçacığı açısından güvenli çağrılar sağlamaya yönelik bir deseni gösterir. Denetimin System.Windows.Forms.Control.InvokeRequired oluşturma iş parçacığı kimliğini çağıran iş parçacığı kimliğiyle karşılaştıran özelliğini sorgular. Farklıysa yöntemini çağırmanız Control.Invoke gerekir.
denetimin WriteTextSafe
TextBoxText özelliğini yeni bir değere ayarlamayı etkinleştirir. yöntemi sorgular InvokeRequired. döndürürsetrue
InvokeRequired, WriteTextSafe
yöntemini yöntemine temsilci Invoke olarak geçirerek özyinelemeli olarak kendisini çağırır. döndürürse InvokeRequiredfalse
, WriteTextSafe
öğesini doğrudan ayarlar TextBox.Text . Olay işleyicisi Button1_Click
yeni iş parçacığını oluşturur ve yöntemini çalıştırır WriteTextSafe
.
private void button1_Click(object sender, EventArgs e)
{
var threadParameters = new System.Threading.ThreadStart(delegate { WriteTextSafe("This text was set safely."); });
var thread2 = new System.Threading.Thread(threadParameters);
thread2.Start();
}
public void WriteTextSafe(string text)
{
if (textBox1.InvokeRequired)
{
// Call this same method but append THREAD2 to the text
Action safeWrite = delegate { WriteTextSafe($"{text} (THREAD2)"); };
textBox1.Invoke(safeWrite);
}
else
textBox1.Text = text;
}
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim threadParameters As New System.Threading.ThreadStart(Sub()
WriteTextSafe("This text was set safely.")
End Sub)
Dim thread2 As New System.Threading.Thread(threadParameters)
thread2.Start()
End Sub
Private Sub WriteTextSafe(text As String)
If (TextBox1.InvokeRequired) Then
TextBox1.Invoke(Sub()
WriteTextSafe($"{text} (THREAD2)")
End Sub)
Else
TextBox1.Text = text
End If
End Sub
Örnek: BackgroundWorker kullanma
Çok iş parçacıklı işlem gerçekleştirmenin System.ComponentModel.BackgroundWorker kolay bir yolu, olay temelli bir model kullanan bileşendir. Arka plan iş parçacığı olayı oluşturur BackgroundWorker.DoWork ve ana iş parçacığıyla etkileşim kurmaz. Ana iş parçacığı, ana iş parçacığının BackgroundWorker.ProgressChanged denetimlerini çağırabilen ve BackgroundWorker.RunWorkerCompleted olay işleyicilerini çalıştırır.
kullanarak BackgroundWorkeriş parçacığı güvenli bir çağrı yapmak için olayı işleyebilir DoWork . Arka plan çalışanının durumu bildirmek için kullandığı iki olay vardır: ProgressChanged ve RunWorkerCompleted. Olay ProgressChanged
, durum güncelleştirmelerini ana iş parçacığına iletmek için kullanılır ve RunWorkerCompleted
olay arka plan çalışanının işini tamamlandığını bildirmek için kullanılır. Arka plan iş parçacığını başlatmak için öğesini çağırın BackgroundWorker.RunWorkerAsync.
Örnek olayda 0'dan 10'a DoWork
kadar sayar ve sayımlar arasında bir saniye boyunca duraklar. Olay işleyicisini ProgressChanged kullanarak sayıyı ana iş parçacığına geri bildirir ve denetimin TextBoxText özelliğini ayarlar. ProgressChanged Olayın çalışması BackgroundWorker.WorkerReportsProgress için özelliği olarak true
ayarlanmalıdır.
private void button1_Click(object sender, EventArgs e)
{
if (!backgroundWorker1.IsBusy)
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int counter = 0;
int max = 10;
while (counter <= max)
{
backgroundWorker1.ReportProgress(0, counter.ToString());
System.Threading.Thread.Sleep(1000);
counter++;
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) =>
textBox1.Text = (string)e.UserState;
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If (Not BackgroundWorker1.IsBusy) Then
BackgroundWorker1.RunWorkerAsync()
End If
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim counter = 0
Dim max = 10
While counter <= max
BackgroundWorker1.ReportProgress(0, counter.ToString())
System.Threading.Thread.Sleep(1000)
counter += 1
End While
End Sub
Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
TextBox1.Text = e.UserState
End Sub
.NET Desktop feedback
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin