我有问题。我编写了一个使用wsHttpBinding的wcf客户端(WPF和c#)。 我正在使用双工。我有一个函数,我每分钟调用一次名为KeepConnection的wcf服务。 我永远不会关闭客户端代理,因为我需要让客户端“在线”一直进行服务回调。但是当在Windows XP上运行这个客户端时,我的应用程序的内存有一个奇怪的问题。当在win 7 / vista上正常运行时,应用程序只在taskmanger中使用40mb的内存。在Xp中每秒不断增加内存的使用。 我在2天内获得了超过700mb。
有没有办法解决这个问题,还是与XP有关。谢谢你的帮助。
服务代码:
/// <summary>
/// Just an empty method for client to keep the connection alive with the service.
/// </summary>
public void KeepConnection()
{
_logger.Debug("Keep alive requested.");
}
我的客户代码。
private InstanceContext instanceContext; //Wcf instance context for callbacks.
public static BootDialog _bootScreen = new BootDialog(); //Boot window.
public static RetryDialog _retryScreen = new RetryDialog(); //Retry window.
public static ProductionServiceClient service; //Wcf service client
public static ClientCallBack clientBack; //Client callback events and handler.
public static ClientTokenResponse ClientToken; //ClientToken from wcf service.
public static int[] ScannerNumbers;
public static IList<HighlightArticleDto> highListArticleList; //List and color of witch list to highligt.
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
private static ClientTokenRequest clientRequest;
private Timer _keepAliveTimer = new Timer();
private void Application_Startup(object sender, StartupEventArgs e)
{
_logger.Trace("Enter Application_Startup().");
int[] scannerNumberList = ParseHandler.GetScannersFromSettingString(Settings.Default.Scanners);
//Saves it globally
App.ScannerNumbers = scannerNumberList;
_logger.Info("Getting {0} scanners for this client.", scannerNumberList.Count());
clientBack = new ClientCallBack();
instanceContext = new InstanceContext(clientBack);
//ToDO : This fix is for XP computer with the http://+:80/Temporary_Listen_Addresses/c269764e-808e-4284-ad7f-4e0eb88ee951/ error.
WSDualHttpBinding binding = new WSDualHttpBinding();
binding.Name = "WsDualTcpEndpoint";
binding.CloseTimeout = new TimeSpan(0, 0, 10);
binding.OpenTimeout = new TimeSpan(0, 0, 10);
//binding.ReceiveTimeout = new TimeSpan(0, 0, 30);
binding.SendTimeout = new TimeSpan(0, 0, 10);
binding.BypassProxyOnLocal = false;
binding.TransactionFlow = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MaxBufferPoolSize = 524288;
binding.MaxReceivedMessageSize = 65536;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = System.Text.Encoding.UTF8;
binding.UseDefaultWebProxy = false;
binding.Security.Mode = WSDualHttpSecurityMode.None;
StringBuilder sb = new StringBuilder();
sb.Append("http://").Append(GetLocalIp()).Append(":808/WSDualOnXP");
_logger.Debug("Client base address : {1}.", sb.ToString());
binding.ClientBaseAddress = new Uri(sb.ToString());
EndpointAddress endpoint = new EndpointAddress(Settings.Default.ServerAddress);
service = new ProductionServiceClient(instanceContext, binding, endpoint);
//2011-08-25 Test utav clientbase
//service = new ProductionServiceClient(instanceContext, "WsDualTcpEndpoint", Settings.Default.ServerAddress);
_logger.Debug("Server address : {0}.", Settings.Default.ServerAddress);
//ToDo Disabled GeneralDialog.
//2011-05-25 Remove this comment if generaldialog wants to be seen.
//if (scannerNumberList.Count() == 0 || String.IsNullOrEmpty(Settings.Default.ServerAddress))
//{
// GeneralDialog dialog = new GeneralDialog();
// dialog.Show();
// return;
//}
//Subscribe to wcf service.
SubscribeToService(scannerNumberList);
//Keep connection to the service alive.
KeepAlive();
//Start timer for highlight list
GetHighLightListTimer();
//Catch unhandled exceptions
this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}
private void KeepAlive()
{
_keepAliveTimer.Interval = 31000;
_keepAliveTimer.Elapsed +=
(
(object o, ElapsedEventArgs args) =>
{
try
{
_keepAliveTimer.Stop();
if (service.State != CommunicationState.Opened)
{
if (service != null) { service.Abort(); }
ShowRetryDialog();
RetryToSubscribe();
}
service.KeepConnection();
}
catch (TimeoutException ex)
{
if (service != null) { service.Abort(); }
ShowRetryDialog();
RetryToSubscribe();
}
catch (CommunicationException ex)
{
if (service.State != CommunicationState.Opened)
{
if (service != null) { service.Abort(); }
ShowRetryDialog();
RetryToSubscribe();
}
}
catch
{
if (service != null) { service.Abort(); }
_keepAliveTimer.Stop();
ShowRetryDialog();
RetryToSubscribe();
}
finally
{
_keepAliveTimer.Start();
}
}
);
_keepAliveTimer.Start();
}
我的客户回调。
#region ClientCallBacks
//When service callbacks to the client this methods will be triggered.
void clientBack_ClientNotified(object sender, ClientNotifiedEventArgs e)
{
throw new NotImplementedException();
}
void clientBack_RemoveFromDisplayEvent(object sender, RemoveFromDisplayEventArgs e)
{
try
{
_logger.Info("Remove from display.");
userControlChairs.Dispatcher.Invoke((Action)(() =>
{
_queueProductionItems.Remove(e.OrderResponse);
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void clientBack_AddToDisplayEvent(object sender, AddToDisplayEventArgs e)
{
try
{
_logger.Info("Add to display.");
userControlChairs.Dispatcher.Invoke((Action)(() =>
{
_queueProductionItems.Add(e.OrderResponse);
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void clientBack_UpdateQueueDisplayEvent(object sender, UpdateQueueDisplayEventArgs e)
{
try
{
_logger.Info("Update queue display.");
userControlQueue.Dispatcher.Invoke((Action)(() =>
{
_queueDisplayItems.Clear();
foreach (OrderDto o in e.UnfinishedOrdersResponse.Orders)
{
_queueDisplayItems.Add(o);
}
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
#endregion
private ObservableOrderResponseQueue _queueProductionItems = new ObservableOrderResponseQueue(); //List of the chairs that will be displayed.
private ObservableCollection<ErrorMessage> _errorMessages = new ObservableCollection<ErrorMessage>(); //List that holds the error message for debug
private ObservableCollection<OrderDto> _queueDisplayItems = new ObservableCollection<OrderDto>();//List of order and quanities left. (DisplayQueue).
private ObservableCollection<DebugInfo> _queueDebugInfo = new ObservableCollection<DebugInfo>(); //
RetryToSubsribe方法。
public void RetryToSubscribe()
{
try
{
WSDualHttpBinding binding = new WSDualHttpBinding();
binding.Name = "WsDualTcpEndpoint";
binding.CloseTimeout = new TimeSpan(0, 1, 0);
binding.OpenTimeout = new TimeSpan(0, 1, 0);
//binding.ReceiveTimeout = new TimeSpan(0, 0, 30);
binding.SendTimeout = new TimeSpan(0, 1, 0);
binding.BypassProxyOnLocal = false;
binding.TransactionFlow = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MaxBufferPoolSize = 524288;
binding.MaxReceivedMessageSize = 65536;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = System.Text.Encoding.UTF8;
binding.UseDefaultWebProxy = false;
binding.Security.Mode = WSDualHttpSecurityMode.None;
StringBuilder sb = new StringBuilder();
sb.Append("http://").Append(GetLocalIp()).Append(":808/WSDualOnXP");
_logger.Debug("Client base address : {1}.", sb.ToString());
binding.ClientBaseAddress = new Uri(sb.ToString());
EndpointAddress endpoint = new EndpointAddress(Settings.Default.ServerAddress);
service = new ProductionServiceClient(instanceContext, binding, endpoint);
ClientTokenRequest request = new ClientTokenRequest();
request.RequestId = NewRequestId;
request.StationNumbers = ScannerNumbers;
clientRequest = request;
service.Subscribe(request);
//Close the retry window.
this.Dispatcher.Invoke((Action)(() =>
{
//Set the background to default.
this.MainWindow.SetResourceReference(Window.BackgroundProperty, "MainBackground");
_retryScreen.Hide();
}));
}
catch (Exception ex)
{
_logger.Error(ex.Message);
}
}
答案 0 :(得分:3)
如果你可以运行windbg并跟进,你可能会发现究竟是什么泄漏。
打开windbg并附加到客户端进程(让它运行一段时间来放大问题,即内存泄漏)
在提示符下输入
If using .NET 2/3.5 .loadby sos mscorwks If using .NET 4 .loadby sos clr
!dumpheap -stat
您将获得按类分组的内存中所有对象的列表。寻找具有最多实例数的那些。希望这会告诉你什么是有问题的代码。
其他选项包括:
!dumpheap -stat -type MyClass的*
这将只显示以MyClass开头的类的实例。
在从进程中分离之前不要关闭windbg,否则会导致进程终止。
答案 1 :(得分:0)
我猜测计时器的Elapsed处理程序中发生了内存泄漏。你能发布RetryToSubscribe()的代码吗?