2010-04-23 35 views
7

Tôi có một chuỗi được quản lý đang chờ, bị chặn, trong một mã không được quản lý (cụ thể, nó trên một cuộc gọi đến NamedPipeServerStream.WaitForConnection() tối đa gọi vào mã không được quản lý, và không cung cấp thời gian chờ).Làm cách nào để chấm dứt chuỗi được quản lý bị chặn trong mã không được quản lý?

Tôi muốn tắt luồng xuống một cách gọn gàng.

Thread.Abort() không có hiệu lực cho đến khi mã trở về lĩnh vực được quản lý, mà nó sẽ không làm cho đến khi khách hàng tạo kết nối, mà chúng tôi không thể đợi).

Tôi cần một cách "gây sốc" nó ra khỏi mã không được quản lý; hoặc một cách để chỉ giết sợi chỉ ngay cả khi nó ở trong vùng đất không được quản lý.

+1

Bất kỳ lý do nào bạn không sử dụng NamedPipeServerStream.BeginWaitForConnection() thay thế? – SpaceghostAli

+1

Về cơ bản vì chuỗi muốn chờ "mãi mãi" cho kết nối (trừ khi tắt máy). Với Begin/End WaitForConnection, tôi phải bắt đầu, chờ một giây, kiểm tra kết nối hoặc hết thời gian chờ và lặp lại thời gian chờ. –

+1

Ok tôi hiểu rồi. Vâng một chút sửa đổi để câu trả lời của dtb sẽ cung cấp cho bạn những gì bạn cần. Thay vì chờ đợi trên asyncResult, hãy đợi trên WaitHandle được chia sẻ mà bạn đã đặt từ mã mà sẵn sàng hủy bỏ chuỗi. – SpaceghostAli

Trả lời

19

Bạn đã thử sử dụng phương pháp không chặn NamedPipeServerStream.BeginWaitForConnection?

using (NamedPipeServerStream stream = ...) 
{ 
    var asyncResult = stream.BeginWaitForConnection(null, null); 

    if (asyncResult.AsyncWaitHandle.WaitOne(5000)) 
    { 
     stream.EndWaitForConnection(asyncResult); 
     // success 
    } 
} 

Bạn không nhất thiết phải sử dụng thời gian chờ cố định. Bạn có thể sử dụng một ManualResetEvent để báo hiệu khi thread nên dừng lại chờ đợi cho các kết nối:

ManualResetEvent signal = new ManualResetEvent(false); 

using (NamedPipeServerStream stream = ...) 
{ 
    var asyncResult = stream.BeginWaitForConnection(_ => signal.Set(), null); 

    signal.WaitOne(); 
    if (asyncResult.IsCompleted) 
    { 
     stream.EndWaitForConnection(asyncResult); 
     // success 
    } 
} 

// in other thread 
void cancel_Click(object sender, EventArgs e) 
{ 
    signal.Set(); 
} 
+0

Tín hiệu cũng cần được đặt bên trong một cuộc gọi lại được truyền đến BeginWaitForConnection. Sau đó, ví dụ sẽ hoàn thành. –

1

Không có cách nào để "gọn gàng" đóng cửa một sợi từ bên ngoài, nếu thread đang chạy mã unmannaged. Có một vài cách để đột ngột Chấm dứt chuỗi, nhưng đó có thể không phải là những gì bạn muốn.

Thay vào đó, bạn nên sử dụng BeginWaitForConnection.

0

Thực ra, giải pháp tôi đã sử dụng (đã xảy ra với tôi khi tôi đang viết câu hỏi), là, sau khi hủy bỏ tất cả các chủ đề, chỉ cần tạo (và ngay lập tức vứt bỏ) một khách hàng cho mỗi luồng.

threads.ForEach(thread=> thread.Abort()); 
    threads.ForEach(thread=> 
       { 
        var client = new PipeClient(ServiceName); 
        client.Connect(); 
        client.Dispose(); 
       }); 

Với sự kết nối, nó sẽ trả về để quản lý mã, và Abort() đá trong (thread bắt ThreadAbortException và làm sạch bản thân lên)

này không làm việc đối với trường hợp chung (ví dụ, câu hỏi đặt ra trong tiêu đề), nhưng nó hoạt động cho tôi ...

+0

Nếu bạn sử dụng chương trình điên rồ này, hãy chắc chắn sử dụng thời gian chờ thích hợp trên Connect, trong trường hợp quá trình khác thiết lập kết nối vào đúng thời điểm, khiến cho chuỗi nghe bị hủy và chuỗi này bị chặn! –

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