2012-03-02 18 views
5

Tôi đang làm việc trên một loại hàng đợi hành động như vậy và tôi muốn chờ một hành động nhất định được thực hiện. Tôi muốn tạo hành động trong chủ đề chính, sau đó chuyển nó tới hàm chuỗi chủ đề (đến cuối hàng đợi) và đợi hành động này được thực hiện. Vì vậy, tôi cần phải phân biệt hành động mà tôi vừa truy vấn đã được thực hiện và chờ đợi.Có an toàn khi chuyển sự kiện từ chuỗi chính đến chuỗi công nhân và đợi không?

Tôi đã một sau (giả) mã và tôi muốn biết

  • là nó làm việc với các chủ đề đối tượng sự kiện Windows an toàn không?
  • nếu có, khái niệm này có hiệu quả không?

type 
    TMyThread = class(TThread); 
    private 
    FEvent: THandle; 
    protected 
    procedure Execute; override; 
    public 
    procedure DoSomething(const AEvent: THandle); 
    end; 

procedure TMyThread.Execute; 
begin 
    // is it working with events thread safe ? 
    SetEvent(FEvent); 
    // the thread will continue, so I can't use WaitFor 
    // but it won't set this specific FEvent handle again 
    // I'm working on such kind of an action queue, so once the action with ID, 
    // here represented by the FEvent will be processed, it's removed from 
    // the action queue 
end; 

procedure TMyThread.DoSomething(const AEvent: THandle); 
begin 
    FEvent := AEvent; 
end; 

// here's roughly what I want to do 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    OnceUsedEvent: THandle; 
begin 
    // the thread is already running and it's instantiated in MyThread 
    // here I'm creating the event for the single request I need to be performed 
    // by the worker thread 
    OnceUsedEvent := CreateEvent(nil, True, False, nil); 
    try 
    // here I'm passing the event handle to the worker thread (like a kind of 
    // a request ID) 
    MyThread.DoSomething(OnceUsedEvent); 
    // and here I want to wait for 10 seconds (and also interrupt this waiting 
    // when the user closes the application if possible ?) for the thread if 
    // performs my request 
    WaitForSingleObject(OnceUsedEvent, 10000); 
    finally 
    // close the event handle 
    CloseHandle(OnceUsedEvent); 
    end; 
    // and continue with something else 
end; 

Cảm ơn!

+0

Việc chờ sự kiện trong trình xử lý sự kiện nút sẽ chặn chuỗi chính, vì vậy đó không phải là điều bạn muốn! Có lẽ bạn có thể sử dụng một sự kiện thay thế (được gọi là bất cứ khi nào thread kết thúc) – jpfollenius

+2

Việc chờ đợi đó sẽ không làm những gì bạn muốn. Nó không thể bị gián đoạn. Và tại sao bạn muốn chặn 10 giây? Đó chỉ là kỳ quặc. –

+0

Lý tưởng nhất là INFINITE; Và đó là để đổi tên hành động. Tôi cần phải vào chế độ chỉnh sửa của nút VirtualTreeView và giữ cho trình chỉnh sửa còn sống cho đến khi tôi nhận được kết quả của hành động đổi tên từ chuỗi (tôi có một trình xử lý sự kiện bổ sung mà tôi cần chuyển kết quả đó nếu đổi tên thành công và khi tôi thoát trình xử lý sự kiện này trình chỉnh sửa bị ẩn). –

Trả lời

4

Vâng, điều đó hoàn toàn ổn. Xử lý được trả về từ CreateEvent có thể được sử dụng tự do bởi tất cả các luồng. Bất cứ điều gì khác sẽ làm cho nó khá vô ích vì đây là việc sử dụng chính của nó :)

+1

Không nhất thiết. Nó có vẻ hợp lý với tôi rằng một xử lý có thể được cụ thể thread, hoặc ít nhất là không vốn thread-an toàn. Nếu một luồng khác muốn truy cập vào cùng một sự kiện, nó có thể là nó cần phải gọi DuplicateHandle, hoặc nó cần phải gọi chính CreateEvent với cùng một tên sự kiện. –

+0

Theo kinh nghiệm, xử lý có thể được sử dụng từ các chủ đề khác - Tôi đã sử dụng các sự kiện theo cách thường xuyên. –

+0

@RobKennedy đó là chính xác những gì tôi đã luôn luôn thực hiện cho đến ngày hôm nay khi tôi thấy một ví dụ mà ai đó vừa có cả hai chủ đề sử dụng cùng một biến xử lý ... –

3

Đừng chờ đợi các luồng trong trình xử lý sự kiện GUI. Đừng làm điều đó bằng cách chờ đợi trên các sự kiện, semaphores hoặc mutexes, sleep() vòng, DoEvents vòng hoặc bất kỳ sự kết hợp của chúng.

Nếu bạn muốn liên lạc với chủ đề chính để báo hiệu rằng có điều gì đó đã được xử lý trong một threadpool, hãy xem API PostMessage().

+0

Lựa chọn thay thế để sử dụng 'PostMessage' khi giao tiếp với tread chính là 1)' Thread .Queue' như được mô tả ở đây [đồng bộ hóa và xếp hàng-với-tham số] (http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/#more-135) (điều này rất hữu ích cho các ứng dụng FireMonkey) hoặc 2) bằng cách sử dụng hàng đợi an toàn 'thread' và bỏ phiếu hàng đợi từ luồng chính với vòng lặp hẹn giờ. –

+0

'đồng bộ hóa và xếp hàng-với-tham số' là OK-ish, nhưng nó thực hiện hai cuộc gọi hệ thống chỉ để tìm ra chuỗi đang chạy trên đó: (Sử dụng bộ hẹn giờ để thăm dò ý kiến ​​là tốt cho việc hiển thị định kỳ giá trị ngày của nhiều biến, nhưng chỉ giới thiệu độ trễ nếu được sử dụng để thăm dò ý kiến ​​một hàng đợi. –

Các vấn đề liên quan