Hướng dẫn sử dụng BackgroundWorker để xây dựng chức năng Chạy nền trong C#

Để hỗ trợ lập trình viên phát triển các chức năng đa tiến trình, tiến trình chạy song song (chạy nhiều tác vụ cùng một lúc mà không phải đợi tiến trình trước hoàn tất) C# đã cung cấp cho bạn lớp Thread trong namspace System.Threading. Tuy nhiên, chắc chắn rằng việc sử dụng Thread đòi hỏi bạn phải có những kiến thức cũng như kiến thức nhất định để có thể xử lý. Đó là nói về Threading.

☛ Bạn có thể tải mã nguồn (source sample) bằng C# tại http://adf.ly/znuem

Trong bài viết này mình sẽ chia sẻ cùng bạn về BackgroundWorker một component trong System.ComponentModel. Đây là lớp được .Net tích hợp nhằm giúp lập trình viên xây dựng, quản lý các tiến trình chạy nền trong ứng dụng dễ dàng hơn và hiệu xuất tốt hơn, dễ dàng hơn so với việc sử dụng Thread.
Hiện tại BackgroundWorker (.Net phiên bản mình sử dụng là 4.0) thì lớp này được cung cấp các thuộc tính sau:

1. Các thuộc tính chủ yếu:
WorkerReportsProgress : mặc định là False. Thuộc tính này nếu là True thì event ProgressChanged sẽ được thực thi (trong này bạn xử lý để hiển thị tiến độ công việc như thanh xử lý tiến trình, % tiến trình).
WorkerSupportsCancellation : mặc định là False. Thuộc tính này nếu là True thì thao tác ngừng tiến trình có hiệu lực.
CancellationPending : biến bool tiếp nhận trạng thái dừng tiến trình. Nếu giá trị là True tức là tiến trình được yêu cầu dừng.
IsBusy: biến bool tiếp ghi nhận trạng thái hoạt động của BackgroundWorker, mặc định là False. Nếu kiểm tra (!IsBusy) thì tức là tiến trình đang bận xử lý.

2. Các sự kiện chính trong lớp BackgroundWorker:
DoWork: các thao tác xử lý công việc (lấy dữ liệu, tìm kiếm, update…) được diễn ra tại đây.
ProgressChanged: các xử lý hiển thị thông báo tiến độ của tiến trình đặt ở đây.
RunWorkerCompleted: các xử lý khi tiến trình hoàn tất hoặc bị ngừng bởi người dùng.

3. Để hiểu rõ hơn về cách sử dụng BackgroundWorker mình xin đưa ra 1 ví dụ cụ thể như sau:
Mình xây dựng 1 ứng dụng đơn giản chạy 1 vòng lặp for để hiển thị lên TextBox lần lượt chuỗi nội dung từ 0->n. Mã nguồn mình Upload tại link cuối bài viết. Nếu bạn quan tâm đến video hướng dẫn thì có thể xem thêm video sau:

(Video hướng dẫn sử dụng BackgroundWorker lập trình đa tiến trình trong C#)

Bạn vui lòng tham khảo các bước sau nhé !

a. Đầu tiên bạn tạo 1 dự án với các Controls như sau:

Hướng dẫn sử dụng BackgroundWorker trong xây dựng chức năng Chạy nền trong CSharp

b. Mã xử lý trong quá trình khởi tạo Form như sau:

public Form1()
        {
            InitializeComponent();
            backgroundWorker1=new BackgroundWorker();
            backgroundWorker1.WorkerReportsProgress=true;
            backgroundWorker1.WorkerSupportsCancellation = true;
            //Đăng ký các event cho backgroundWorker1;
            backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.RunWorkerCompleted +=
                new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
        }

c. Hàm xử lý tiến trình, trong hàm này các bạn đặt các thao tác xử lý của mình vào đây nhé, ở đây mình đặt thao tác xử lý vòng for cho phép hiển thị chuỗi tương ứng với chỉ số i:

private int demQuaTrinhXuLyDangChay = 0;
private void hamChuaCacThaoTacXuLyBangDoWorkBackground(DoWorkEventArgs e)
{
    for (Int64 i = Convert.ToInt64(txtChayTu.Text.Trim()); i < Convert.ToInt64(txtChayDen.Text.Trim()); i++)
    {
        //Đoạn này để chỉnh thời gian tạm ngừng giữa mỗi lần lặp của vòng for (lần xử lý);
        //Giá trị Sleep tính như sau 1000 = 1 giây;
        Thread.Sleep(Convert.ToInt16(txtThoiGianTamNgungGiuaCacLanXuLy.Text));
        //Kiểm tra trạng thái backgroundWork nếu bị ngừng thì dừng xử lý;
        if (backgroundWorker1.CancellationPending)
        {
            e.Cancel = true;
            return;
        }
        //Đoạn này để gọi event ReportProgress trong quá trình xử lý lần lặp i;
        //Ở đây mình đơn giản chỉ chạy dòng chữ ... cứ vậy cho đến khi xử lý hoàn tất thì hiển thị thông báo;
        demQuaTrinhXuLyDangChay++;
        backgroundWorker1.ReportProgress(demQuaTrinhXuLyDangChay);
        txtKetQuaXuLyTienTrinh.Text += i + ": [" + demQuaTrinhXuLyDangChay + "] lần xử lý "+i+" hoàn tất !\r\n";
        //Đoạn này để hiển thị tiến trình đang xử lý đến lần lặp i;
        txtKetQuaXuLyTienTrinh.SelectionStart = txtKetQuaXuLyTienTrinh.Text.Length;
        txtKetQuaXuLyTienTrinh.ScrollToCaret();
    }
}

d. Bạn viết mã xử lý cho các hàm sự kiện backgroundWorker1 như sau:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    //Gọi hàm xử lý tiến trình trong sự kiện DoWork;
    hamChuaCacThaoTacXuLyBangDoWorkBackground(e);
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    lblQuaTrinhXuLyTienTrinhHienTai.Text += ".";
    //Nếu label có hơn 3 dấu chấm thì gán lại giá trị rỗng cho thuộc tính Text;
    //Quá trình này sẽ được lặp lại cho đến khi tiến trình hoàn tất;
    //Bạn có thể sử dụng hình ảnh thể hiện dạng (loading...), đang xử lý để hiển thị cho người dùng biết;
    if (lblQuaTrinhXuLyTienTrinhHienTai.Text.Length >= 4)
    {
        lblQuaTrinhXuLyTienTrinhHienTai.Text = string.Empty;
    }
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        MessageBox.Show("Tiến trình xử lý được kết thúc bởi người dùng !", "Thông báo");
    }
    else
    {
        MessageBox.Show("Tiến trình xử lý hoàn tất !", "Thông báo");
        lblQuaTrinhXuLyTienTrinhHienTai.Text = string.Empty;
    }
}

e. Bạn viết mã xử lý sự kiện Click cho nút Chạy và Ngừng như sau:

private void btnChayTienTrinhXuLy_Click(object sender, EventArgs e)
{
    //Nếu backgroundWorker1 đang không trong quá trình xử lý thì chạy nó để bắt đầu xử lý;
    if(!backgroundWorker1.IsBusy)
    {
        backgroundWorker1.RunWorkerAsync();
    }
    //....
    //Bạn có thể viết mã hành xử thêm ở đây nếu tiến trình đang bận để tương tác;
}

private void btnNgungTienTrinhXuLy_Click(object sender, EventArgs e)
{
    //Ngừng tiến trình đang xử lý;
    backgroundWorker1.CancelAsync();
    txtKetQuaXuLyTienTrinh.Text = string.Empty;
    demQuaTrinhXuLyDangChay = 0;
}

Bây giờ bạn tiến hành Build dự án của mình để xem kết quả nhé !. Đối với việc xử lý các tiến trình khác các bạn làm tương tự, tùy vào mục đích yêu cầu mà xây dựng các tiến trình làm việc với nhau sao cho hợp lý.

☛ Bạn có thể tải mã nguồn (source sample) bằng C# tại http://adf.ly/znuem

Qua chia sẻ này mình mong sẽ giúp ích cho các bạn trong quá trình tiếp cận ngôn ngữ lập trình .Net (C#) để học tập cũng như phát triển ứng dụng của mình tốt hơn.
Cảm ơn sự quan tâm của bạn với chia sẻ về việc sử dụng BackgroundWorker trong việc lập trình đa tiến trình trong .NetFramwork.

Related Posts

About The Author

5 Comments

  1. Avatar
    Hoàng Minh
    01/08/2018
  2. Avatar
    Bình
    12/02/2015
    • Cù Kim Ngọc
      Cù Kim Ngọc
      12/02/2015
      • Avatar
        mkbyme
        20/12/2015
        • Cù Kim Ngọc
          Cafe Freelancer
          27/12/2015

Add Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.