Không bao giờ, sử dụng Thread.Suspend
. Vấn đề chính với nó là 99% thời gian bạn không thể biết những gì mà thread đang làm khi bạn đình chỉ nó. Nếu chủ đề đó giữ khóa, bạn sẽ dễ dàng xâm nhập vào tình huống bế tắc, v.v. Hãy nhớ rằng mã bạn đang gọi có thể có được/giải phóng khóa đằng sau hậu trường. Win32 có một API tương tự: SuspendThread
và ResumeThread
. Các tài liệu sau đây cho SuspendThread
cho một bản tóm tắt tốt đẹp của sự nguy hiểm của các API:
http://msdn.microsoft.com/en-us/library/ms686345(VS.85).aspx
Chức năng này được thiết kế chủ yếu để sử dụng bởi bộ dò lỗi. Nó không được dùng để đồng bộ hóa luồng. Gọi SuspendThread trên một chủ sở hữu một đối tượng đồng bộ hóa, chẳng hạn như một mutex hoặc phần quan trọng, có thể dẫn đến bế tắc nếu chuỗi cuộc gọi cố gắng lấy một đối tượng đồng bộ thuộc sở hữu của một chuỗi bị treo. Để tránh tình trạng này, một luồng trong một ứng dụng không phải là trình gỡ lỗi sẽ báo hiệu luồng khác để treo chính nó. Chuỗi đích phải được thiết kế để theo dõi tín hiệu này và phản hồi một cách thích hợp.
Cách thích hợp để tạm dừng một chuỗi vô thời hạn là sử dụng ManualResetEvent
. Chủ đề có nhiều khả năng lặp, thực hiện một số công việc. Cách dễ nhất để đình chỉ các chủ đề là phải có các chủ đề "kiểm tra" sự kiện này mỗi lần lặp, như vậy:
while (true)
{
_suspendEvent.WaitOne(Timeout.Infinite);
// Do some work...
}
Bạn chỉ định một thời gian chờ vô hạn nên khi sự kiện này không hiệu, thread sẽ chặn vô thời hạn, cho đến khi sự kiện này được báo hiệu tại thời điểm mà luồng sẽ tiếp tục tại nơi nó đã dừng lại.
Bạn sẽ tạo ra sự kiện này như sau:
ManualResetEvent _suspendEvent = new ManualResetEvent(true);
Tham số true
nói sự kiện này để bắt đầu ra ở trạng thái báo hiệu.
Khi bạn muốn tạm dừng thread, bạn thực hiện như sau:
_suspendEvent.Reset();
Và để tiếp tục các chủ đề:
_suspendEvent.Set();
Bạn có thể sử dụng một cơ chế tương tự như tín hiệu thread để thoát ra và chờ đợi cả hai sự kiện, phát hiện sự kiện nào được báo hiệu.
Just for fun tôi sẽ cung cấp một ví dụ hoàn chỉnh:
public class Worker
{
ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
ManualResetEvent _pauseEvent = new ManualResetEvent(true);
Thread _thread;
public Worker() { }
public void Start()
{
_thread = new Thread(DoWork);
_thread.Start();
}
public void Pause()
{
_pauseEvent.Reset();
}
public void Resume()
{
_pauseEvent.Set();
}
public void Stop()
{
// Signal the shutdown event
_shutdownEvent.Set();
// Make sure to resume any paused threads
_pauseEvent.Set();
// Wait for the thread to exit
_thread.Join();
}
public void DoWork()
{
while (true)
{
_pauseEvent.WaitOne(Timeout.Infinite);
if (_shutdownEvent.WaitOne(0))
break;
// Do the work here..
}
}
}
tôi sẽ phải đi và đọc ebook đó. Tôi chưa bao giờ gặp sự cố với việc Tạm dừng/Tiếp tục lại. –