Tôi đang sử dụng netNamedPipeBinding
để thực hiện liên lạc WCF liên thông từ một ứng dụng cửa sổ đến dịch vụ cửa sổ.Ngoại lệ WCF nhận được khi đóng kết nối với các cuộc gọi lại đang sử dụng
Bây giờ ứng dụng của tôi đang chạy tốt trong tất cả các tài khoản khác (sau khi đấu với phần ngoại lệ WCF của tôi vì bất kỳ ai đã làm việc với WCF đều biết ..) nhưng lỗi này là một trong số đó tỏ ra khá kiên cường.
Để vẽ hình ảnh về kịch bản của tôi: dịch vụ cửa sổ của tôi có thể được xếp hàng để thực hiện một số công việc tại bất kỳ thời điểm nào thông qua một nút được nhấn trong ứng dụng cửa sổ và sau đó nói qua số netNamedPipeBinding
. -truyền thông) nếu bạn không quen thuộc và bắt đầu một yêu cầu để thực hiện công việc này, (trong trường hợp này là một thủ tục tải lên tập tin) nó cũng ném callbacks (sự kiện) mỗi vài giây khác nhau, từ tiến trình tập tin đến tốc độ chuyển vv. ứng dụng cửa sổ, vì vậy có một số tích hợp máy chủ-máy chủ khá chặt chẽ; đây là cách tôi nhận được sự tiến bộ của tôi về những gì đang chạy trong cửa sổ dịch vụ của tôi trở lại ứng dụng cửa sổ của tôi.
Bây giờ, tất cả là tuyệt vời, các vị thần WCF tương đối hài lòng với tôi ngay bây giờ ngoài một ngoại lệ khó chịu mà tôi nhận được mỗi khi tôi tắt ứng dụng sớm (đó là một kịch bản hoàn toàn hợp lệ). Trong khi chuyển đang diễn ra, và callbacks được bắn khá nặng nề, tôi nhận được lỗi này:
System.ServiceModel.ProtocolException:
The channel received an unexpected input message with Action
'http://tempuri.org/ITransferServiceContract/TransferSpeedChangedCallback'
while closing. You should only close your channel when you are not expecting
any more input messages.
Bây giờ tôi hiểu lỗi đó, nhưng tiếc là tôi không thể đảm bảo để đóng kênh của tôi sau không bao giờ nhận được bất kỳ messsages đầu vào hơn, như người dùng có thể tắt ứng dụng bất cứ lúc nào do đó công việc sẽ vẫn tiếp tục trong nền của dịch vụ windows (giống như cách hoạt động của trình quét vi-rút). Người dùng có thể bắt đầu và đóng ứng dụng công cụ quản lý chiến thắng nhiều như họ muốn mà không bị nhiễu.
Bây giờ lỗi, tôi nhận ngay sau khi thực hiện cuộc gọi Unsubscribe()
là cuộc gọi cuối cùng thứ hai trước khi chấm dứt ứng dụng và những gì tôi tin là cách ưu tiên để ngắt kết nối ứng dụng khách WCF. Tất cả việc hủy đăng ký trước khi đóng kết nối chỉ đơn giản là xóa id ứng dụng khỏi một mảng được lưu trữ cục bộ trên dịch vụ wcf dịch vụ giành chiến thắng (vì đây là một cá thể ĐƯỢC CHIA SẺ bởi cả dịch vụ giành chiến thắng và ứng dụng windows làm dịch vụ giành chiến thắng có thể thực hiện công việc tại các sự kiện theo lịch trình của chính nó) và sau khi loại bỏ mảng id khách hàng tôi thực hiện, những gì tôi hy vọng (cảm thấy) nên là một ngắt kết nối sạch sẽ. Kết quả của việc này, ngoài việc nhận được ngoại lệ, ứng dụng của tôi bị treo, giao diện người dùng trong tổng số khóa, thanh tiến trình và mọi thứ ở giữa, với tất cả các dấu hiệu chỉ đến tình trạng đua hoặc bế tắc WCF [tiếng thở dài], nhưng bây giờ tôi khá hiểu biết và tôi nghĩ đây là một tình huống tương đối biệt lập và đọc ngoại lệ như-là, tôi không nghĩ rằng đó là vấn đề 'chủ đề', vì nó nói thêm một vấn đề ngắt kết nối sớm sau đó xoắn tất cả các chủ đề của tôi vào tình trạng lộn xộn, có lẽ gây ra khóa.
Tiếp cận của tôi Unsubscribe()
trên client trông như thế này:
public void Unsubscribe()
{
try
{
// Close existing connections
if (channel != null &&
channel.State == CommunicationState.Opened)
{
proxy.Unsubscribe();
}
}
catch (Exception)
{
// This is where we receive the 'System.ServiceModel.ProtocolException'.
}
finally
{
Dispose();
}
}
Và Dispose()
phương pháp của tôi, mà nên thực hiện ngắt kết nối sạch:
public void Dispose()
{
// Dispose object
if (channel != null)
{
try
{
// Close existing connections
Close();
// Attempt dispose object
((IDisposable)channel).Dispose();
}
catch (CommunicationException)
{
channel.Abort();
}
catch (TimeoutException)
{
channel.Abort();
}
catch (Exception)
{
channel.Abort();
throw;
}
}
}
Và các dịch vụ WCF Subscription()
đối tác và lớp thuộc tính (để tham khảo) trên dịch vụ windows máy chủ (không có gì phức tạp ở đây và ngoại lệ của tôi xảy ra phía khách hàng):
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class TransferService : LoggableBase, ITransferServiceContract
{
public void Unsubscribe()
{
if (clients.ContainsKey(clientName))
{
lock (syncObj)
{
clients.Remove(clientName);
}
}
#if DEBUG
Console.WriteLine(" + {0} disconnected.", clientName);
#endif
}
...
}
Giao diện của:
[ServiceContract(
CallbackContract = typeof(ITransferServiceCallbackContract),
SessionMode = SessionMode.Required)]
public interface ITransferServiceContract
{
[OperationContract(IsInitiating = true)]
bool Subscribe();
[OperationContract(IsOneWay = true)]
void Unsubscribe();
...
}
Interface hợp đồng gọi lại, nó không làm bất cứ điều gì rất thú vị, chỉ cần gọi sự kiện thông qua các đại biểu vv Lý do tôi bao gồm này là để hiển thị bạn thuộc tính của tôi. Tôi đã làm giảm bớt một bộ bế tắc đã được bao gồm UseSynchronizationContext = false
:
[CallbackBehavior(UseSynchronizationContext = false,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class TransferServiceCallback : ITransferServiceCallbackContract
{ ... }
Thực sự hy vọng ai đó có thể giúp tôi! Cảm ơn rất nhiều = :)
Tôi không biết về vấn đề cụ thể, nhưng để biết những lộn xộn luồng âm thanh * có thể * do cách WCF sử dụng đồng bộ ngữ cảnh (đó là thông qua hình thức trong winforms vv). –
Cảm ơn Marc, yep đã bắt được tôi và tôi đã giảm bớt một tập hợp các deadlocks bằng cách đọc về vấn đề đó, mẹo để đặt 'UseSynchronizationContext = false' trên hợp đồng gọi lại;) Tôi sẽ thêm điều này vào ví dụ của mình. – GONeale
ah, đúng; tốt để xem bạn đã có nó bảo hiểm, p –