05-10-12, 01:44 AM
كاتب الموضوع : samerselo
سألني أحد الإخوة عن مشكلة واجهته عند تنفيذ عملية معينة على مسار آخر ومحاولته إظهار النتيجة على النموذج فإذا افترضنا أنه لدينا إجراء بسيطا ينفذ عملية ما ونفذناه على مسار آخر Thread غير المسار الرئيسي الذي تنفذ عليه عمليات البرنامج وأن ذلك الإجراء يحتوي على كود يقوم بضبط قيمة الخاصية Text لصندوق نصوص على النموذج فعند تنفيذ الكود ستحصل على رسالة خطأكود :
Cross-thread operation not valid: Control 'TextBox1' accessed from a thread other than the thread it was created on.
كود :
Imports System.Threading
Public Class Form1
Private Sub Button1_Click() Handles Button1.Click
Dim th As New Thread(AddressOf DoLongOperation)
th.Start()
End Sub
Private Sub DoLongOperation()
Me.TextBox1.Text = "Something"
End Sub
End Class
الآن سأقوم بإضافة فئة Class جديد للمشروع يتم عبره تنفيذ العملية الطويلة التي نريد تنفيذها على مسار آخر وسأقوم بتسميتها MyStopWatch في الوقت الحالي وبما أننا سنتعامل مع المسارات سنحتاج للاستيراد التالي قبل تعريف الفئة
كود :
Imports System.Threading
كود :
Public Class ReturnValueEventArgs
Inherits EventArgs
Private _ReturnValue As String
Public ReadOnly Property ReturnVlaue() As String
Get
Return _ReturnValue
End Get
End Property
Public Sub New(ByVal RetVal As String)
_ReturnValue = RetVal
End Sub
End Class
كود :
Public Event ReturnValue(ByVal sender As Object, ByVal e As ReturnValueEventArgs)
كود :
Private _MyTimer As Stopwatch
كود :
Private Sub DoProcessing()
Do
Dim Ret = _MyTimer.Elapsed.Hours & ":" & _
_MyTimer.Elapsed.Minutes & ":" & _
_MyTimer.Elapsed.Seconds & ":" & _
_MyTimer.Elapsed.Milliseconds
RaiseEvent ReturnValue(Me, New ReturnValueEventArgs(Ret))
Loop Until _MyTimer.IsRunning = False
End Sub
وسيكون لدينا إجراء لبدء تنفيذ المؤقت على المسار الثاني باسم StartTimer بحيث يكون كوده على الشكل
كود :
Public Sub StartTimer()
_MyTimer.Reset()
_MyTimer.Start()
Dim th As New Thread(AddressOf DoProcessing)
th.Start()
End Sub
كود :
Public Sub StopTimer()
_MyTimer.Stop()
End Sub
كود :
Imports System.Threading
Public Class MyStopWtach
Public Class ReturnValueEventArgs
Inherits EventArgs
Private _ReturnValue As String
Public ReadOnly Property ReturnVlaue() As String
Get
Return _ReturnValue
End Get
End Property
Public Sub New(ByVal RetVal As String)
_ReturnValue = RetVal
End Sub
End Class
Public Event ReturnValue(ByVal sender As Object, ByVal e As ReturnValueEventArgs)
Private _MyTimer As New Stopwatch
Public Sub StartTimer()
_MyTimer.Reset()
_MyTimer.Start()
Dim th As New Thread(AddressOf DoProcessing)
th.Start()
End Sub
Private Sub DoProcessing()
Do
Dim Ret = _MyTimer.Elapsed.Hours & ":" & _
_MyTimer.Elapsed.Minutes & ":" & _
_MyTimer.Elapsed.Seconds & ":" & _
_MyTimer.Elapsed.Milliseconds
RaiseEvent ReturnValue(Me, New ReturnValueEventArgs(Ret))
Loop Until _MyTimer.IsRunning = False
End Sub
Public Sub StopTimer()
_MyTimer.Stop()
End Sub
End Class