Gặp vấn đề về Thread.Sleep trong WPF C#

Em có 1 đoạn code:

private void StartTask(object sender,RoutedEventArgs e)
    {
        this.Message.Text = "Nhớ làm việc đi nhé!";
        Thread.Sleep(2000);
        this.Close();           
    }

Em không hiểu sao khi em click vào button cho cái event chạy thì chương nó dừng trước rồi nó mới đổi cái Message.Text và tắt chương trình??? Hình như code nó ưu tiên cái Thread.Sleep cho chạy trước!
Mấy bác bày đường chỉ lỗi sao cho cái chương trình chạy code theo trình tự, cái Message.Text chạy trước -> Thread.Sleep -> this.Close???

1 Like

Chương trình mặc định là single thread, tức là chỉ có 1 luồng duy nhất gọi là main thread xử lý toàn bộ công việc một cách tuần tự. Việc “vẽ” những thay đổi trên giao diện được thực hiện trong hàm WndProc (mặc định ẩn đi) cụ thể là trong tin nhắn WM_PAINT (thực thi khoảng 60 lần /s) chứ không phải là dòng set text trong code.

Khi set text xong gọi thread.sleep ngay nó sẽ dừng main thread ngay tại thời điểm đó. Lúc đó chắc chắn là UI không được “vẽ lại” và nó sẽ không được vẽ trong suốt 2s thực thi sleep nên nó sẽ đơ cứng trong thời gian sleep.

3 Likes

Tránh việc này cần có nhiều hơn 1 luồng xử lý dữ liệu. Và đẩy các công việc cần trễ nhiều ra một luồng khác main thread.

Có thể sử dụng (hoặc google để biết cách dùng):
Thread, Task, Async, BackgroundWorker.

1 Like

Bạn gọi Application.DoEvents() sau khi set text nhé.
Chương trình WPF cũng như Winform, delphi cũng thế, xử lí các thao tác liên quan đến ui bằng các tin nhắn (Windows Messages - WM)
Khi các tin nhắn quá nhiều thì chương trình sẽ xếp chúng lại vào hàng đợi và lần lượt thực hiện.
Nếu bạn dùng Sleep thì quá trình xử lí WM cũng bị dừng lại luôn -> không update
Khi dùng Application.DoEvents() thì sẽ buộc ct xử lí hết các WM còn trong hàng đợi.
Code của bác:

private void StartTask(object sender,RoutedEventArgs e)
    {
        this.Message.Text = "Nhớ làm việc đi nhé!";
        Application.DoEvents();
        Thread.Sleep(2000);
        this.Close();           
    }
4 Likes

Thêm reference System.Windows.Forms.dll và thêm using System.Windows.Forms; để có Application.DoEvents.

1 Like

Em cảm ơn mấy bác! :))

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?