Trang 1 trên 1

DCS - Lỗi ngớ ngẫn của vb6 khi sử dụng array với "with" statement. (This array is fixed or temporarily locked)

Đã gửi: T.Năm 13/07/2017 8:57 am
gửi bởi Dark.Cosmos
  1. Option Explicit
  2.  
  3. Private Type dtTest
  4.     A As Long
  5.     B As Long
  6. End Type
  7.  
  8. Private aryTest() As dtTest
  9.  
  10.  
  11.  
  12. Private Sub Form_Initialize()
  13.     Const c& = 10
  14.     ReDim aryTest(c) As dtTest
  15.     Dim i&: For i = 0 To 10
  16.         With aryTest(i)
  17.             .A = i
  18.             .B = -i
  19.         End With
  20.     Next
  21.     Call ShowTestInfo
  22. End Sub
  23.  
  24. Private Sub Form_Terminate()
  25.     Erase aryTest()
  26. End Sub
  27.  
  28.  
  29.  
  30. Private Sub ShowTestInfo()
  31.     Dim c&: c = UBound(aryTest)
  32.     Label1 = CStr(c)
  33.     Label2 = CStr(aryTest(c).A)
  34.     Label3 = CStr(aryTest(c).B)
  35. End Sub
  36.  
  37. Private Sub TestAryVsWithStm(aT() As dtTest)
  38. On Error GoTo lE:
  39.     Dim c&: c = UBound(aT)
  40.     c = c + 1
  41.     ReDim Preserve aT(c) As dtTest
  42.     aT(c).A = c
  43.     aT(c).B = -c
  44. Exit Sub
  45. lE: Call MsgBox("Error: " & Err.Description & vbCrLf & "Error Number: " & Err.Number, vbCritical): Call Err.Clear
  46. End Sub
  47.  
  48.  
  49.  
  50. Private Sub Command1_Click()
  51.     Dim c&: c = c = UBound(aryTest)
  52.     If (aryTest(c).A = c And aryTest(c).B = -c) Then
  53.         Call TestAryVsWithStm(aryTest())
  54.         Call ShowTestInfo
  55.     End If
  56. End Sub
  57.  
  58. Private Sub Command2_Click()
  59.     Dim c&: c = c = UBound(aryTest)
  60.     With aryTest(c)
  61.         If (.A = c And .B = -c) Then
  62.             Call TestAryVsWithStm(aryTest())
  63.             Call ShowTestInfo
  64.         End If
  65.     End With
  66. End Sub
  67.  


Với đoạn code ở trên (có đính kèm project mẫu ở dưới), mình test lỗi bằng cách cho Redim mảng động aryTest() được truyền như là một đối số cho thủ tục TestAryVsWithStm.
Về mặt lý thuyết, code ở thủ tục Command1_Click và Command2_Click là như nhau. Chỉ là ở Command2_Click có sử dụng statement: "With ... End With" để đơn giản hóa code. (https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/with-end-with-statement)

Khi gọi thủ tục Command1_Click thì code hoạt động bình thường.
Nhưng khi gọi thủ tục Command2_Click thì sẽ nhận được 1 lỗi: This array is fixed or temporarily locked.
Mình có google về lỗi này nhưng hầu như toàn nêu lý do tương tự như bài viết của msdn, hoặc có thể mình tìm chưa kĩ: https://msdn.microsoft.com/en-us/library/aa231012(v=vs.60).aspx

Cái lỗi này khiến mình bị ăn hành suốt 2 hôm trời, thậm chí mình có thử dùng API "__vbaAryUnlock" trong "msvbvm60.dll" nhưng vẫn không khắc phục được.

Mò mẫm đến giờ mới té ngữa ra là do sử dụng statement: "With ... End With". #-o
Nay mạn phép viết bài này chia sẻ với mong muốn có thể giúp được phần nào cho những ai gặp trường hợp giống mình. Nếu bài viết có gì sai sót thì rất mong mọi người có thể góp ý để hoàn thiện.

Thanks!

Re: DCS - Lỗi ngớ ngẫn của vb6 khi sử dụng array với "with" statement. (This array is fixed or temporarily locked)

Đã gửi: T.Bảy 23/09/2017 2:07 am
gửi bởi truongphu
Tôi đã đọc nhiều bài viết của Dark.Cosmos, Rất hay và tôi học hỏi thêm nhiều điều.

Trạng thái With... End With thường dùng cho đối tượng (Class), do vậy khi dùng với Type thì chạy không được!

Gởi Dark.Cosmos project tôi tạm sửa với thêm class, chạy êm với with =D>

Re: DCS - Lỗi ngớ ngẫn của vb6 khi sử dụng array với "with" statement. (This array is fixed or temporarily locked)

Đã gửi: T.Sáu 13/07/2018 2:41 pm
gửi bởi Dark.Cosmos
Cảm ơn bác TruongPhu nhiều ạ.
Lúc mới tập tành code cháu toàn tham khảo code của bác và mọi người trên forum mình không đấy ạ.