2012-07-29 41 views
17

Đây là vấn đề tôi đã điều tra trong tuần trước và không thể tìm thấy giải pháp nào. Tìm thấy các bài đăng hỏi giống nhau nhưng không bao giờ nhận được câu trả lời, hy vọng điều này cũng sẽ giúp người khác.Làm thế nào để hủy bỏ một dòng từ dịch vụ WCF mà không đọc nó để kết thúc?

Tôi có dịch vụ WCF trả về đối tượng chứa stream bên trong nó. Tôi sử dụng basicHttpBinding với truyền trực tiếp và Mtom để gửi cho khách hàng.

Khách hàng gọi dịch vụ WCF và đóng proxy ngay sau khi nhận được các đối tượng phản ứng.

Tiếp theo, khách hàng sẽ đọc dòng nó nhận được từ các dịch vụ WCF và ghi nó vào một tập tin trên đĩa địa phương. Tất cả điều này hoạt động tốt.

Vấn đề của tôi là khi khách hàng muốn hủy bỏ các hoạt động và dừng tải dữ liệu từ các dịch vụ WCF. Nếu tôi gọi .close() trên luồng, ví dụ: serverReply.DataStream.Close(); thì nó sẽ chặn và đọc toàn bộ luồng từ dịch vụ WCF cho đến khi kết thúc trước khi tiếp tục. Luồng có thể khá lớn và mạng không phải lúc nào cũng nhanh.

này là rất không mong muốn cho cả hai sử dụng tài nguyên mạng, mà về cơ bản bị lãng phí trên dữ liệu đó không có người sử dụng nữa. Và vì basicHttpBinding chỉ cho phép hai kết nối TCP đồng thời (theo mặc định) cho máy chủ dịch vụ WCF, nó chặn các nỗ lực kết nối khác cho đến khi luồng được đọc cho đến khi kết thúc.

Tôi có thể tăng số lượng kết nối đồng thời, nhưng đó sẽ là một giải pháp tồi vì nó sẽ tạo ra lỗ mở cho sự cố.

Ví dụ, 20 tải aborted rằng vẫn đang tải dữ liệu đến vứt nó đi. Tôi cần phải thực hiện việc chuyển nhượng hoàn toàn.

Trên máy khách, đối tượng luồng chỉ là lớp Stream thông thường, vì vậy nó chỉ có phương pháp đóng, không có gì khác.

Gọi .close() hoặc .abort() trên đối tượng proxy không giúp đỡ, không phá hủy nó bằng cách sử dụng .dispose() hoặc bất kỳ phương pháp nào khác. Ở phía máy chủ, tôi xử lý sự kiện OperationContext.OperationCompleted nhưng không được kích hoạt cho đến khi dữ liệu từ stream được đọc cho đến khi kết thúc.

Vì vậy, câu hỏi là, làm cách nào để đóng/hủy luồng mà không đọc hoàn toàn?

+0

Bất kỳ may mắn nào với điều này? – Schultz9999

+0

Đau khổ cùng một vấn đề trong khi gửi các tập tin thực sự lớn ... có vẻ như phải thiếu một cái gì đó thực sự rõ ràng. có lẽ sẽ phải thực hiện chunking như một workaround. –

Trả lời

0

Bạn đã thử chơi xung quanh với binding.MaxBufferSize chưa?
Các bạn đã thử chơi xung quanh với các thiết lập file app.config của bạn ví dụ:

<bindings> 
    <wsHttpBinding> 
    <binding name="default" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" 
      closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" > 
     <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" 
        maxDepth="64" maxStringContentLength="2147483647" /> 
    </binding> 

    </wsHttpBinding> 
</bindings> 

tôi sẽ hạn chế tối đa các timeouts và kiên chiều dài đệm và cố gắng hủy bỏ hoặc gần và xem những gì sẽ xảy ra.

+1

Tôi đã thử nhưng không hiệu quả. Khi máy chủ bắt đầu gửi luồng, nó sẽ không dừng lại cho đến khi tất cả nó được máy khách nhận. Đóng proxy không làm gì cả. Nó giống như không có cách nào rõ ràng để ngăn chặn giao tiếp. Khi khách hàng ngừng đọc luồng, tôi có thể thấy cửa sổ tcp không quay lại máy chủ. Và máy chủ định kỳ gửi một cửa sổ thăm dò bằng không để xem liệu máy khách đã sẵn sàng để đọc lại chưa. Và tất nhiên khách hàng gửi lại cửa sổ không lần nữa. Điều này xảy ra mãi mãi cho đến khi quá trình này bị giết. – Yev

+0

Bạn đã thử đọc luồng chỉ bằng Lớp HttpClient và xem liệu bạn có thể đóng luồng không? –

+0

Làm cách nào để thực hiện điều đó mà không cần gọi dịch vụ WCF? Tôi đã thực hiện một số nghiên cứu khác và có vẻ như không có cách nào để đóng luồng từ phía máy khách. Tôi đã thử một cách tiếp cận khác. Tôi đã tạo một dịch vụ khác, một dịch vụ điều khiển và cố gắng đóng luồng từ đó (phía máy chủ). Nhưng không may mắn. Một cái gì đó chỉ không hoạt động, nó không đóng hoặc vứt bỏ. – Yev

1

Sau khi điều tra, tôi thấy rằng WCF khách hàng sẽ tiếp tục đọc từ dòng cho đến khi closeTimeout ellapsed, sau đó nó sẽ hủy bỏ kết nối. Bạn có thể giảm closeTimeout trên máy khách để giảm thiểu vấn đề.

Chú ý: Bạn nên quấn mã mà disposes một dòng vào khối try/catch. Phương thức stream.Dispose() sẽ ném ra TimeoutException mà phanh một hướng dẫn là not throwing exceptions in Dispose method.

0

Tôi nghĩ bạn chỉ đang nhận bộ đệm sau khi đóng. Bạn nên đặt maxBufferSize thành giá trị thấp hơn.

Bạn cũng có thể muốn hạn chế lượng dữ liệu được đọc trên máy chủ bằng cách gói luồng của bạn và ghi đè đọc. Sử dụng các đoạn nhỏ hơn nếu bạn có một ứng dụng băng thông thấp và trả về một số tương ứng từ phương thức đọc để khớp với số tiền bạn thực sự đọc. Điều này sẽ hạn chế tỷ lệ lấp đầy của bộ đệm.

Bài kiểm tra của riêng tôi về chủ đề này liên quan đến việc tôi viết NeverEndingStream và luôn trả về dữ liệu. Tại một số điểm tôi gọi là đóng trên máy khách sau đó gần như ngay lập tức đóng được gọi trên máy chủ. Điều này cho thấy rằng bộ đệm chỉ đơn thuần là làm trống bởi vì rõ ràng nó sẽ không bao giờ có thể đọc luồng của tôi cho đến khi kết thúc.

Nếu bạn vẫn gặp sự cố thì tôi khuyên bạn nên theo dõi thời gian của phương thức Đọc trên luồng đã ghi đè của mình. Nếu currentReadtime - lastReadTime là> x thì bạn có thể gọi Close và ném một ngoại lệ. Điều đó sẽ giết nó chắc chắn.

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