Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 20 kết quả

Đề tài: Xử lý lỗi Cross-thread | Cross-thread operation not valid

  1. #1
    Ngày gia nhập
    06 2007
    Nơi ở
    TP.HCM
    Bài viết
    113

    Talking Xử lý lỗi Cross-thread | Cross-thread operation not valid

    Khi bạn sử dụng thread, trong thread đang chạy bạn xử lý với các control và đôi lúc bạn gặp phải cái lỗi "Cross-thread operation not valid: ...". Cái lỗi này khi xài VS 2003 thì bạn không gặp phải, nhưng với > VS2005 thì chắc chắn là gặp. Và cách xử lý như sau:

    Mô tả một đoạn mã gặp lỗi:

    Visual C# Code:
    1. using System.Threading;
    2.  
    3.    public partial class Form1 : Form
    4.     {
    5.         public Form1()
    6.         {
    7.             InitializeComponent();
    8.         }
    9.  
    10.         private void AddItemN(int n)
    11.         {
    12.             for (int i = 0; i < n; i++)
    13.             {
    14.                 lsbCross.Items.Add(i);
    15.             }
    16.         }
    17.  
    18.         private void AddItem()
    19.         {
    20.             for (int i = 0; i < 10; i++)
    21.             {
    22.                 lsbCross.Items.Add(i);
    23.             }
    24.         }
    25.  
    26.         private void CrossThread()
    27.         {
    28.             AddItemN(20);
    29.         }
    30.  
    31.         private void btnCross_Click(object sender, EventArgs e)
    32.         {
    33.             ThreadStart ths = new ThreadStart(AddItem);
    34.             Thread thd = new Thread(ths);
    35.             thd.Start();
    36.         }
    37.     }

    Demo có lỗi:
    và đây là cái lỗi chương trình trên quẳng ra:
    Cross-thread operation not valid: Control 'lsbCross' accessed from a thread other than the thread it was created on.
    Cách xử lý thì bạn chỉ cần thay các hàm AddItem (không có tham số truyền cho hàm), AddItemN(int n) (có tham số truyền cho hàm) bằng các hàm đã xử lý cross thread như sau:

    Visual C# Code:
    1. #region Xử lý Cross Thread
    2.         //Xử lý cross có truyền tham số (sử dụng hàm AddItemN)
    3.         private delegate void dlgAddItemN(int n);
    4.         private void AddItemN(int n)
    5.         {
    6.             //nếu control nào đó không có properties InvokeRequired thì xài luôn this.InvokeRequired không cần phải thông qua control
    7.             if (this.lsbCross.InvokeRequired)
    8.             {
    9.                 this.Invoke(new dlgAddItemN(AddItemN), n);
    10.             }
    11.             else
    12.             {
    13.                 for (int i = 0; i < n; i++)
    14.                 {
    15.                     this.lsbCross.Items.Add(i);
    16.                 }
    17.             }
    18.         }
    19.  
    20.         //Xử lý cross thread không truyền tham số cho hàm (sử dụng hàm AddItem)
    21.         private delegate void dlgAddItem();
    22.         private void AddItem()
    23.         {
    24.             if (this.lsbCross.InvokeRequired)
    25.             {
    26.                 this.Invoke(new dlgAddItem(AddItem));
    27.             }
    28.             else
    29.             {
    30.                 for (int i = 0; i < 10; i++)
    31.                 {
    32.                     this.lsbCross.Items.Add(i);
    33.                 }
    34.             }
    35.         }
    36.         #endregion

    Demo đã xử lý lỗi:
    Attached Files Attached Files

    Gác Kiếm

  2. #2
    Ngày gia nhập
    10 2007
    Nơi ở
    HCMUNS
    Bài viết
    459

    đôi lúc bạn gặp phải cái lỗi "Cross-thread operation not valid: ...". Cái lỗi này khi xài VS 2003 thì bạn không gặp phải, nhưng với > VS2005 thì chắc chắn là gặp.
    Cho nhc hỏi tại sao lại có dzụ này ? Có gì khác à ?
    Keep moving forward!

    ... Retired ...

  3. #3
    Ngày gia nhập
    06 2007
    Nơi ở
    TP.HCM
    Bài viết
    113

    Trích dẫn Nguyên bản được gửi bởi nhc1987 Xem bài viết
    Cho nhc hỏi tại sao lại có dzụ này ? Có gì khác à ?
    Không biết nữa! Nhưng lúc trước xài với máy trên trường (2003) thì không bị nhưng với máy ở nhà (2005) thì vậy . Mà hỏi ông thầy ổng kêu không biết nó xử lý cái gì mà lên 2005 nó cần phải như vậy.

    Gác Kiếm

  4. #4
    Ngày gia nhập
    10 2007
    Nơi ở
    HCMUNS
    Bài viết
    459

    Talking Cross-thread operation not valid

    Đây là 1 warning ( 0 phải là lỗi ) của VS khi Debug ( nếu chạy bình thường 0 phải debug thì sẽ 0 gặp ) , nó là warning vì thỉnh thoảng nó có thể gây ra lỗi

    Nguyên nhân :

    warning này sẽ xảy ra khi bạn chạy 1 method trên 1 control từ 1 thread 0 phải là thread mà control được tạo

    cụ tỉ như dầy :
    - bạn tạo 1 control C trên thread A
    - bạn tạo 1 thread B
    - trong thread B bạn chạy 1 method của C , chẳng hạn như gọi C.Text = "" , -> warning

    warning chỉ xảy ra với những method mà có sử dụng đến handle của control C , chẳng hạn như Show , Hide , set_Text ( là thủ tục Set() của property Text ) , set_Size , ...

    Handle của control là gì :

    Nếu bạn dùng .NET mà trước kia chưa dùng Win32 và sau này cũng 0 đụng gì tới Win32 ( tức là 100% .NET đó , được dẩy thì rất quý :-D ) , bạn sẽ 0 biết về handle của control . Đại khái nó là địa chỉ của 1 window trong bộ nhớ . Class System.Windows.Forms.Control là 1 wrapper cho Window trong Win32

    Khi bạn gọi thủ tục như Control.Show , nó sẽ gọi các hàm của Win32 , như là hàm ShowWindow([Handle của Window mà class Control đang wrap ] , [... 1 vài tham số khác])

    Thấy là thủ tục Control.Show() sẽ dùng đến handle của control

    "thread mà control được tạo" là gì :

    Dim C as new Control -> đây 0 phải là lúc "control được tạo" hay đầy đủ là "handle của control chưa được tạo"

    1 control bắt đầu có handle khi nó gọi hàm Win32 CreateWindow hoặc CreateWindowEx

    Nó gọi hàm đó lúc nào , chỉ người viết ra class System.Windows.Forms.Control mới biết , hoặc bạn có thể đọc code của nó dùng .NET Reflector

    Và "thread mà control được tạo" chính là thread mà class Control gọi hàm Win32 CreateWindow

    Cách bỏ qua warning

    Đây là warning cho nên bạn có thể bỏ qua nó , như mọi warning khác . Bạn chỉ cần gọi thủ tục đây :
    System.Windows.Forms.Control.CheckForIllegalCrossT hreadCalls = False

    Cách giải quyết warning

    Bạn cần gọi các thủ tục "mà có dùng đến handle của control" trên "thread mà control được tạo"

    VD đoạn code mà sẽ gây ra warning :

    Code:
    1. Public Class Form1
       2.  
       3.     Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
       4.         'Tạo 1 thread mà sẽ dùng tới handle của Form1
       5.         Dim T As New Threading.Thread(AddressOf CrossThreadOperation)
       6.         T.Start()
       7.     End Sub
       8.  
       9.     Private Sub CrossThreadOperation()
      10.         'Thủ tục CrossThreadOperation có dùng tới handle của Form1
      11.         Me.Text = Date.Now.ToString 'Warning ở đây
      12.     End Sub
      13.  
      14. End Class

    Khi click dô form , warning sẽ xảy ra , để ý là bạn phải chạy Debug thì mới thấy warning

    Class Control có các method mà cho phép chạy 1 method trên thread của Control , đó là Invoke ( đồng bộ ) , BeginInvoke + EndInvoke ( 0 đồng bộ )

    Để dùng các method đó , bạn cung cấp cho nó 1 delegate tới method mà bạn muốn chạy .

    Code:
     1. Public Class Form1
       2.  
       3.     Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
       4.         'Tạo 1 thread mà sẽ dùng tới handle của Form1
       5.         Dim T As New Threading.Thread(AddressOf CrossThreadOperation)
       6.         T.Start()
       7.     End Sub
       8.  
       9.     Private Sub CrossThreadOperation()
      10.         'Tạo delegate
      11.         Dim MI As New MethodInvoker(AddressOf SetText)
      12.         'Chạy delegate MI trên thread của Form1
      13.         Me.Invoke(MI)
      14.     End Sub
      15.  
      16.     Private Sub SetText()
      17.         Me.Text = Date.Now.ToString
      18.     End Sub
      19.  
      20. End Class
    Khuyến mãi : Control.Invoke nó làm cái gì

    Control.Invoke(delegate) sẽ send 1 message đến "Window mà Control đang wrap" , dùng hàm Win32 SendMessage , message đó sẽ có địa chỉ của method của delegate ( tiếng anh là function pointer )

    Window nhận message trên thread của nó , qua hàm WndProc ( hàm này được windows gọi chớ 0 phải window gọi , :-D windows là hệ điều hành ) , message nằm trong tham số của WndProc

    Khi "Window mà Control đang wrap" nhận được message qua hàm WndProc , Control ( có toàn quyền xử lý hàm WndProc , WndProc chính là hàm mà class Control pass dô hàm CreateWindow ) sẽ chạy function pointer đi kèm trong message , function đó sẽ được chạy trên thread của Window

    Chấm hết , hi vọng bạn 0 lẫn lộn giữa Control , Window , Instance của Control :-D

    (Kỳ Nam - caulacbovb)

    P/s: chịu khó đọc code VB tí nhé , Để nguyên gốc tài liệu luôn

    Một bài viết khác của sunflower: http://forums.congdongcviet.com/showthread.php?t=5752
    Keep moving forward!

    ... Retired ...

  5. #5
    Ngày gia nhập
    04 2007
    Bài viết
    134

    Trích dẫn Nguyên bản được gửi bởi sunflower Xem bài viết
    Không biết nữa! Nhưng lúc trước xài với máy trên trường (2003) thì không bị nhưng với máy ở nhà (2005) thì vậy . Mà hỏi ông thầy ổng kêu không biết nó xử lý cái gì mà lên 2005 nó cần phải như vậy.
    Thầy gì lạ vậy

  6. #6
    Ngày gia nhập
    02 2009
    Bài viết
    7

    Mặc định Xử lý lỗi Cross-thread | Cross-thread operation not valid

    vậy cho mình hỏi khi nào .InvokeRequired trả về giá trị True, hoặc False.
    Nếu trả về là False thì phải sử lý như thế nào vì trả về True thì hàm Invoke sau đó mới chạy.

  7. #7
    Ngày gia nhập
    11 2007
    Bài viết
    294

    InvokeRequired mà là false thì không cần Invoke nữa. Chả cần xử lý gì cả.
    Is the moon rising...

  8. #8
    Ngày gia nhập
    10 2010
    Nơi ở
    Biên Hòa
    Bài viết
    562

    ngoài ra mình còn cách nào khác nữa ko bạn, và bạn có thể thik mình hiểu thêm vì sao dùng delegate . Thanks
    Đã được chỉnh sửa lần cuối bởi Yin Yang : 27-04-2011 lúc 08:05 AM. Lý do: spam quote

  9. #9
    Ngày gia nhập
    03 2011
    Bài viết
    30

    Bạn ơi mình chưa hiểu lắm ở thuộc tính InvokeRequired, giải thích rõ jum mình nhe!!

  10. #10
    Ngày gia nhập
    07 2009
    Nơi ở
    C:\Windows
    Bài viết
    103

    đây , rất rõ, cụ thể và chi tiết :

    http://msdn.microsoft.com/en-us/libr...=VS.90%29.aspx
    Đọc đề
    Xé đề
    Chửi thề
    Ra về

Các đề tài tương tự

  1. Sửa giúp lỗi Cross-Thread trong bài truyền nhận file qua mạng LAN
    Gửi bởi faq.c trong diễn đàn Nhập môn lập trình C#, ASP.NET
    Trả lời: 2
    Bài viết cuối: 10-12-2012, 07:15 AM
  2. Lỗi Cross-thread operation not valid và cách khắc phục
    Gửi bởi chitvivo trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 6
    Bài viết cuối: 23-07-2012, 09:10 PM
  3. Cross-thread operation not valid: Control 'txt_1' accessed from a thread other than?
    Gửi bởi ndp1007 trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 3
    Bài viết cuối: 01-03-2012, 12:20 AM
  4. Trả lời: 0
    Bài viết cuối: 16-02-2012, 10:37 PM
  5. lỗi Cross-thread operation not valid khi dùng thread
    Gửi bởi Riku trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 1
    Bài viết cuối: 13-04-2011, 02:50 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn