Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 6 của 6
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    fix cross-thread nhưng không chạy hàm dưới chế độ background được

    Tình hình là mình có làm 1 cái form, khi xảy ra thuộc tính form_load thì sẽ lấy dữ liệu từ database load lên gridview, mình dùng backgroundworker để cho nó chạy nền nhưng khi chạy nền thì bị lỗi "Cross-thread operation not valid".

    Mình fix lỗi này theo bài này: http://diendan.congdongcviet.com/showthread.php?t=5794
    Sau khi fix thì ko bị lỗi này nhưng lại không chạy nền được, khi form load thì không thao tác được trên form mà phải đợi nó chạy xong backgroundworker.DoWork.

    Dưới đây là code của mình mong mọi người hướng dẫn


    form_load
    Mã:
    private void ctrl_thietBiDien_Load(object sender, EventArgs e)
    {
                BackgroundWorker backgroundWorker = new BackgroundWorker();
                backgroundWorker.DoWork += LayDanhSachThietBiDien;
                backgroundWorker.RunWorkerAsync();
    }
    hàm xử lý đã add delegate
    Mã:
    private delegate void ThreadLayDanhSachThietBiDien(object sender, DoWorkEventArgs doWorkEventArgs);
    private void LayDanhSachThietBiDien(object sender, DoWorkEventArgs doWorkEventArgs)
    {
                if (gView_main.InvokeRequired)
                {
                    Invoke(new ThreadLayDanhSachThietBiDien(LayDanhSachThietBiDien), sender, doWorkEventArgs);
                }
                else
                {
                    busThietBiDien tbdBUS = new busThietBiDien();
                    List<ThietBiDien> ds = tbdBUS.LayDanhSachThietBiDien();
    
                    gView_main.Rows.Clear();
                    for (int i = 0; i < ds.Count; i++)
                    {
                        gView_main.Rows.Add(i + 1, ds[i].MaThietBi, ds[i].TenThietBi, ds[i].CongSuat, ds[i].CongSuatHaoHut, ((ds[i].LoaiCongSuatHaoHut) ? "W" : "%"), ds[i].HeSoDeBa);
                    }
                }
    }

    View more random threads:


  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi zakiviet
    Tình hình là mình có làm 1 cái form, khi xảy ra thuộc tính form_load thì sẽ lấy dữ liệu từ database load lên gridview, mình dùng backgroundworker để cho nó chạy nền nhưng khi chạy nền thì bị lỗi "Cross-thread operation not valid".

    Mình fix lỗi này theo bài này: http://diendan.congdongcviet.com/showthread.php?t=5794
    Sau khi fix thì ko bị lỗi này nhưng lại không chạy nền được, khi form load thì không thao tác được trên form mà phải đợi nó chạy xong backgroundworker.DoWork.

    Dưới đây là code của mình mong mọi người hướng dẫn


    form_load
    Mã:
    private void ctrl_thietBiDien_Load(object sender, EventArgs e)
    {
                BackgroundWorker backgroundWorker = new BackgroundWorker();
                backgroundWorker.DoWork += LayDanhSachThietBiDien;
                backgroundWorker.RunWorkerAsync();
    }
    hàm xử lý đã add delegate
    Mã:
    private delegate void ThreadLayDanhSachThietBiDien(object sender, DoWorkEventArgs doWorkEventArgs);
    private void LayDanhSachThietBiDien(object sender, DoWorkEventArgs doWorkEventArgs)
    {
                if (gView_main.InvokeRequired)
                {
                    Invoke(new ThreadLayDanhSachThietBiDien(LayDanhSachThietBiDien), sender, doWorkEventArgs);
                }
                else
                {
                    busThietBiDien tbdBUS = new busThietBiDien();
                    List<ThietBiDien> ds = tbdBUS.LayDanhSachThietBiDien();
    
                    gView_main.Rows.Clear();
                    for (int i = 0; i < ds.Count; i++)
                    {
                        gView_main.Rows.Add(i + 1, ds[i].MaThietBi, ds[i].TenThietBi, ds[i].CongSuat, ds[i].CongSuatHaoHut, ((ds[i].LoaiCongSuatHaoHut) ? "W" : "%"), ds[i].HeSoDeBa);
                    }
                }
    }
    trong vòng for bạn thêm hàm Application.DoEvent() xem có thao tác được ko

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi tuandoi1
    trong vòng for bạn thêm hàm Application.DoEvent() xem có thao tác được ko
    Vẫn không đc bạn à [IMG]images/smilies/smile.png[/IMG]

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Bạn sửa như này xem dc ko gView_main.Invoke(new ThreadLayDanhSachThietBiDien(LayDanhSachThietBiDie n), sender, doWorkEventArgs);

  5. #5
    Trích dẫn Gửi bởi hngdsu
    Như bạn thấy, do bạn đã "delegate" cho thread chính thực hiện phần lớn công việc load dữ liệu nên xảy ra hiện tượng "treo" chương trình cho đến khi việc này thực hiện xong. Mục đích khi dùng backgroundWorker là để nó thực hiện công việc "có thể diễn ra trong thời gian dài" thay cho thread chính. Cụ thể ở đây là việc kết nối đến database và lấy dữ liệu lên. Còn việc gán đống dữ liệu đó để hiện lên gridview thì lại diễn ra trong thời gian khá ngắn. BackgroundWorker có sự kiện Completed để làm điều này mà.
    Rất cảm bạn rất nhiều mình đã làm được [IMG]images/smilies/smile.png[/IMG], đồng thời cũng giải quyết đc vấn đề cuả mình là khi load background như vậy hay là thread thì cái gridview của mình ko dùng đc scrollbar, còn dùng code của bạn thì chạy rất ngon rồi [IMG]images/smilies/smile.png[/IMG]

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Mình sẽ phân tích từng bước của hàm LayDanhSachThietBiDien.

    1. if (gView_main.InvokeRequired)
    Bước này chắc chắn trả về true vì ở cái đoạn else bạn có "đụng" đến một control do thread chính tạo ra (gView_main). Chương trình sẽ nhảy đến đoạn invoke

    2. Invoke(new ThreadLayDanhSachThietBiDien(LayDanhSachThietBiDie n), sender, doWorkEventArgs);
    Đoạn lệnh này sẽ yêu cầu chương trình thực hiện lại hàm LayDanhSachThietBiDien bằng thread chính. Chương trình sẽ quay lại câu if, lưu ý là từ bây giờ, thread chính sẽ thực hiện lệnh chứ không còn là backgroundWorker nữa.

    3. if (gView_main.InvokeRequired)
    Kết quả sẽ là false vì gView_main được truy xuất bởi chính thread tạo ra nó. Chương trình thực hiện tiếp đoạn else.

    Như bạn thấy, do bạn đã "delegate" cho thread chính thực hiện phần lớn công việc load dữ liệu nên xảy ra hiện tượng "treo" chương trình cho đến khi việc này thực hiện xong. Mục đích khi dùng backgroundWorker là để nó thực hiện công việc "có thể diễn ra trong thời gian dài" thay cho thread chính. Cụ thể ở đây là việc kết nối đến database và lấy dữ liệu lên. Còn việc gán đống dữ liệu đó để hiện lên gridview thì lại diễn ra trong thời gian khá ngắn. BackgroundWorker có sự kiện Completed để làm điều này mà.


    Mã:
    private void ctrl_thietBiDien_Load(object sender, EventArgs e){            BackgroundWorker backgroundWorker = new BackgroundWorker();            backgroundWorker.DoWork += backgroundWorker_DoWork;            backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;            backgroundWorker.RunWorkerAsync();} private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e){            busThietBiDien tbdBUS = new busThietBiDien();            List<ThietBiDien> ds = tbdBUS.LayDanhSachThietBiDien();            e.Result = ds;} private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){            List<ThietBiDien> ds = e.Result as List<ThietBiDien>;            if (ds == null)            {                        return;            }             for (int i = 0; i < ds.Count; i++)            {                        gView_main.Rows.Add(i + 1, ds[i].MaThietBi, ds[i].TenThietBi, ds[i].CongSuat, ds[i].CongSuatHaoHut, ((ds[i].LoaiCongSuatHaoHut) ? "W" : "%"), ds[i].HeSoDeBa);            }}

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •