2012-02-04 40 views
8

Tôi đang cố sử dụng các đường ống có tên lần đầu tiên. Trong tài liệu MS tìm thấy here, nó khẳng định rằng:NamedPipeServerStream.EndWaitForConnection() chỉ bị treo khi sử dụng

EndWaitForConnection phải được gọi đúng một lần cho tất cả các cuộc gọi đến BeginWaitForConnection.

Vì vậy, tôi đang cố trở thành một lập trình viên giỏi và làm theo tài liệu, nhưng EndWaitForConnection() chỉ bị treo vô thời hạn khi tôi sử dụng nó.

Vì vậy, tôi đã tước mã của mình xuống mức tối thiểu để xem liệu tôi có thể cách ly vấn đề này nhưng không có súc sắc. Tôi đã rút đoạn mã sau ra khỏi lớp tôi đã viết. Tôi đã sửa đổi nó để nó bắt đầu chờ đợi vào một kết nối đường ống sau đó ngay lập tức cố gắng dừng chờ đợi vào kết nối ống:

private void WaitForConnectionCallBack(IAsyncResult result) 
{ 

} 

public void Start() 
{ 
    var tempPipe = new NamedPipeServerStream("TempPipe", 
              PipeDirection.In, 
              254, 
              PipeTransmissionMode.Message, 
              PipeOptions.Asynchronous); 

    IAsyncResult result = tempPipe.BeginWaitForConnection(
            new AsyncCallback(WaitForConnectionCallBack), this); 

    tempPipe.EndWaitForConnection(result); // <----- Hangs on this line right here 
} 

1) Tại sao nó treo trên EndWaitForConnection()? Nếu tôi muốn tắt máy chủ của mình trước khi tôi nhận được kết nối, làm cách nào tôi có thể hủy cuộc gọi lại số BeginWaitForConnection() này?

2) Giả sử rằng tôi không có vấn đề được đề cập ở trên. Điều gì xảy ra nếu 2 khách hàng cố gắng kết nối với đường ống được đặt tên của tôi rất nhanh chóng?

Tôi có nhận được cuộc gọi lại cho mỗi người không, hoặc tôi có phải đợi để nhận thông báo kết nối đầu tiên sau đó gọi lại EndWaitForConnection()WaitForConnectionCallBack() một lần nữa để bắt đầu nghe lại cho khách hàng tiếp theo?

Loại thứ hai có vẻ giống như một điều kiện đua với tôi, bởi vì tôi có thể không thiết lập trình nghe kết nối đủ nhanh.

+0

Theo thiết kế, cuộc gọi đó chỉ nên được sử dụng trong phương thức gọi lại của bạn (WaitForConnectionCallBack). Bạn hủy bỏ nó bằng cách gọi tempPipe.Close(). –

+0

Vâng, tôi đã tự mình xảy ra kết luận đó. Về cơ bản tôi thấy rằng gọi tempPipe.Close() được gọi lại thường xuyên di chuyển ngay lập tức, vấn đề là, tôi đã có nó thiết lập để ngay lập tức gọi EndWaitForConnection, nhưng kể từ khi ống được đóng cửa bởi sau đó, nó ném một ngoại lệ. Vì vậy, tôi đã phải quấn một tuyên bố thử xung quanh đó và không làm gì trong tuyên bố bắt. Đây có phải là giải pháp đúng không? Nó có vẻ hơi cẩu thả với tôi để đóng ống, biết rằng nó sẽ buộc một ngoại lệ trong callback của bạn mà bạn sẽ phải bắt. – Ultratrunks

+0

Điều đó hoàn toàn bình thường. –

Trả lời

8

Vì vậy, một bộ xương cơ bản của giải pháp đó là làm việc đối với tôi là như sau:

private void WaitForConnectionCallBack(IAsyncResult result) 
{ 
    try 
    { 
     PipeServer.EndWaitForConnection(result); 

     /// ... 
     /// Some arbitrary code 
     /// ... 
    } 
    catch 
    { 
     // If the pipe is closed before a client ever connects, 
     // EndWaitForConnection() will throw an exception. 

     // If we are in here that is probably the case so just return. 
     return; 
    } 
} 

Đây là mã Server.

public void Start() 
{ 
    var server= new NamedPipeServerStream("TempPipe", 
              PipeDirection.In, 
              254, 
              PipeTransmissionMode.Message, 
              PipeOptions.Asynchronous); 

    // If nothing ever connects, the callback will never be called. 
    server.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), this); 

    // ... arbitrary code 

// EndWaitForConnection() was not the right answer here, it would just wait indefinitely 
// if you called it. As Hans Passant mention, its meant to be used in the callback. 
// Which it now is. Instead, we are going to close the pipe. This will trigger 
// the callback to get called. 

// However, the EndWaitForConnection() that will excecute in the callback will fail 
// with an exception since the pipe is closed by time it gets invoked, 
// thus you must capture it with a try/catch 

    server.Close(); // <--- effectively closes our pipe and gets our 
         //  BeginWaitForConnection() moving, even though any future 
         //  operations on the pipe will fail. 
} 
+0

FYI Xem [C# UnauthorizedAccessException khi bật MessageMode cho đường ống chỉ đọc có tên (lớp NamedPipeClientStream)] (http://stackoverflow.com/questions/32739224/c-sharp-unauthorizedaccessexception-when-enabling-messagemode-for-read-only -name) cho các thông tin khác về cách sử dụng chế độ 'Message'. – OmegaMan

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