在XP C#WCF客户端内存泄漏 [英] C# WCF client Memory leak on XP

查看:180
本文介绍了在XP C#WCF客户端内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题。我有编码正在使用的wsHttpBinding WCF客户端(WPF和C#)。
和I'm使用双面。我有我打电话每分钟叫KeepConnection WCF服务的功能。
和我,因为我需要让客户端在线的所有时间服务回调从来没有关闭客户端代理。但在Windows XP上运行该客户端时,我有与运行在正常的win 7 / Vista的应用中只使用40MB的内存在taskmanger我application.When的记忆一个奇怪的问题。在XP中不断加大内存的使用情况每一秒。
我得到了700MB的2天。



有没有办法解决这个问题,或者是XP有关。 。感谢您的帮助。



服务代码:

  ///< ;总结> 
///只为客户端一个空方法永葆与服务的连接。
///< /总结>
公共无效KeepConnection()
{
_logger.Debug(保持活动要求。);
}



我的客户端代码。

 私人的InstanceContext的InstanceContext; //回调WCF实例上下文。 

公共静态BootDialog _bootScreen =新BootDialog(); //启动窗口。
公共静态RetryDialog _retryScreen =新RetryDialog(); //重试窗口。

公共静态ProductionServiceClient服务; // WCF服务的客户端

公共静态ClientCallBack clientBack; //客户端回调的事件和处理程序。
公共静态ClientTokenResponse ClientToken; // ClientToken从WCF服务。
公共静态INT [] ScannerNumbers;
公共静态的IList< HighlightArticleDto> highListArticleList; //列表和女巫列表的颜色highligt。
私人静态只读记录仪_logger = LogManager.GetCurrentClassLogger();
私有静态ClientTokenRequest的ClientRequest;
私人定时器_keepAliveTimer =新的Timer();

私人无效Application_Startup(对象发件人,StartupEventArgs E)
{
_logger.Trace(输入Application_Startup()。);

INT [] = scannerNumberList ParseHandler.GetScannersFromSettingString(Settings.Default.Scanners);

//全球$ B $保存它b = App.ScannerNumbers scannerNumberList;

_logger.Info(获取{0}扫描器此客户端。scannerNumberList.Count());

clientBack =新ClientCallBack();
的InstanceContext =新的InstanceContext(clientBack);

// TODO:此修复程序是XP的电脑与HTTP:// +:80 / Temporary_Listen_Addresses / c269764e-808e-4284-ad7f-4e0eb88ee951 /错误。
WSDualHttpBinding绑定=新WSDualHttpBinding();
binding.Name =WsDualTcpEndpoint;
binding.CloseTimeout =新时间跨度(0,0,10);
binding.OpenTimeout =新时间跨度(0,0,10);
//binding.ReceiveTimeout =新时间跨度(0,0,30);
binding.SendTimeout =新时间跨度(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 =新的StringBuilder();
sb.Append(HTTP://).Append(GetLocalIp())追加(:808 / WSDualOnXP)。

_logger.Debug(客户端基址:{1},sb.ToString());

binding.ClientBaseAddress =新的URI(sb.ToString());

的EndpointAddress端点=新的EndpointAddress(Settings.Default.ServerAddress);
服务=新ProductionServiceClient(的InstanceContext,装订,终点);

// 2011-08-25测试utav clientbase
//服务=新ProductionServiceClient(的InstanceContext,WsDualTcpEndpoint,Settings.Default.ServerAddress);

_logger.Debug(服务器地址:{0},Settings.Default.ServerAddress);

//待办事项残疾人GeneralDialog。
//删除2011-05-25如果generaldialog希望看到此评论。
//如果(scannerNumberList.Count()== 0 || String.IsNullOrEmpty(Settings.Default.ServerAddress))
// {
// GeneralDialog对话框=新GeneralDialog();
// dialog.Show();
//返回;
//}

//订阅WCF服务。
SubscribeToService(scannerNumberList);

//保持连接到服务活着。
的KeepAlive();

//开始为亮点列表
GetHighLightListTimer定时器();

//捕获未处理的异常
this.DispatcherUnhandledException + =新System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}

私人无效的KeepAlive()
{
_keepAliveTimer.Interval = 31000;
_keepAliveTimer.Elapsed + =

(对象o,ElapsedEventArgs参数)=>
{

{
_keepAliveTimer.Stop ();

如果(service.State = CommunicationState.Opened!)
{
如果{service.Abort()(服务!= NULL);}
ShowRetryDialog();
RetryToSubscribe();
}

service.KeepConnection();
}
赶上(TimeoutException异常前)
{
如果(!=服务NULL){service.Abort();}

ShowRetryDialog();
RetryToSubscribe();
}
赶上(前的CommunicationException)
{
如果(service.State = CommunicationState.Opened)
{
如果(服务= NULL){service.Abort();! }

ShowRetryDialog();
RetryToSubscribe();
}
}

{
如果(服务!= NULL){service.Abort(); }
_keepAliveTimer.Stop();

ShowRetryDialog();
RetryToSubscribe();
}
终于
{
_keepAliveTimer.Start();
}
}
);

_keepAliveTimer.Start();
}

和我的客户端回调。

 #地区ClientCallBacks 
//当服务回调到客户端这种方法将被触发。

无效clientBack_ClientNotified(对象发件人,ClientNotifiedEventArgs E)
{
抛出新NotImplementedException();
}

无效clientBack_RemoveFromDisplayEvent(对象发件人,RemoveFromDisplayEventArgs E)
{

{
_logger.Info(从显示屏上删除。 );

userControlChairs.Dispatcher.Invoke((动作)(()=>
{
_queueProductionItems.Remove(e.OrderResponse);
}));
}
赶上(异常前)
{
MessageBox.Show(ex.Message);
}
}

无效clientBack_AddToDisplayEvent(对象发件人,AddToDisplayEventArgs E)
{

{
_logger.Info( 添加显示。);

userControlChairs.Dispatcher.Invoke((动作)(()=>
{
_queueProductionItems.Add(e.OrderResponse);
}));
}
赶上(异常前)
{
MessageBox.Show(ex.Message);
}
}

无效clientBack_UpdateQueueDisplayEvent(对象发件人,UpdateQueueDisplayEventArgs E)
{

{
_logger.Info( 更新队列显示。);

userControlQueue.Dispatcher.Invoke((动作)(()=>
{
_queueDisplayItems.Clear();
的foreach(OrderDto o在e.UnfinishedOrdersResponse .Orders)
{
_queueDisplayItems.Add(O);
}

}));
}
赶上(异常前)
{
MessageBox.Show(ex.Message);
}
}

#endregion

私人ObservableOrderResponseQueue _queueProductionItems =新ObservableOrderResponseQueue(); //将要显示的椅子列表。
私人的ObservableCollection<&的ErrorMessage GT; _errorMessages =新的ObservableCollection<&的ErrorMessage GT;(); //保存调试
私人的ObservableCollection<错误信息清单; OrderDto> _queueDisplayItems =新的ObservableCollection< OrderDto>(); //名单的顺序和quanities离开了。 (DisplayQueue)。
私人的ObservableCollection< debuginfo软> _queueDebugInfo =新的ObservableCollection< debuginfo软>(); //



RetryToSubsribe方法。

 公共无效RetryToSubscribe()
{


{
WSDualHttpBinding绑定=新WSDualHttpBinding();
binding.Name =WsDualTcpEndpoint;
binding.CloseTimeout =新时间跨度(0,1,0);
binding.OpenTimeout =新时间跨度(0,1,0);
//binding.ReceiveTimeout =新时间跨度(0,0,30);
binding.SendTimeout =新时间跨度(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 =新的StringBuilder();
sb.Append(HTTP://).Append(GetLocalIp())追加(:808 / WSDualOnXP)。

_logger.Debug(客户端基址:{1},sb.ToString());

binding.ClientBaseAddress =新的URI(sb.ToString());

的EndpointAddress端点=新的EndpointAddress(Settings.Default.ServerAddress);

服务=新ProductionServiceClient(的InstanceContext,装订,终点);

ClientTokenRequest要求=新ClientTokenRequest();
request.RequestId = NewRequestId;
request.StationNumbers = ScannerNumbers;

的ClientRequest =请求;

service.Subscribe(请求);

//关闭重试窗口。
this.Dispatcher.Invoke((动作)(()=方式>
{
//将背景设为默认值
this.MainWindow.SetResourceReference(Window.BackgroundProperty, MainBackground);

_retryScreen.Hide();
}));

}
赶上(异常前)
{
_logger.Error(ex.Message);
}

}


解决方案

如果你可以运行的WinDbg,并请跟随你可能会找出究竟泄漏。




  • 您的winxp的机器开上WinDbg中并连接到客户端程序(让它运行一段时间,以放大问题,即内存泄漏)


  • 在提示符下键入





 如果使用.NET 2 / 3.5 
.loadby索斯mscorwks
如果使用.NET 4
.loadby SOS CLR





  • 然后运行




dumpheap! - 统计




您会得到所有的内存类分组对象的列表。寻找那些拥有最实例数的人。 。希望这会给你一个什么样是有问题的代码指示



其他的选项是:




!dumpheap -stat型
MyClass的*




这会告诉你只有开始的类的实例与MyClass的。



从进程分离否则将杀死你的进程之前不要关闭WinDbg的。


I have a problem. I have coded a wcf client (WPF and c#) that is using wsHttpBinding. And I´m using duplex. I have a function that i call the wcf service every minute called KeepConnection. And i never close the client proxy because i need to have the client "online" all the time for service callbacks. But when running this client on Windows XP i have a strange problem with the memory of my application.When running normally on win 7 /vista the application only uses 40mb of memory in taskmanger. In Xp in constantly increase the use of memory every second. I got over 700mb on 2 days.

Is there a way to fix this or is it XP related. Thanks for help.

Service code:

    /// <summary>
    /// Just an empty method for client to keep the connection alive with the service.
    /// </summary>
    public void KeepConnection()
    {
        _logger.Debug("Keep alive requested.");
    }

My client code.

    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();
    }

And My client Callbacks.

    #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 method.

        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);
        }

    }

解决方案

if you can run windbg and follow along you might find out what exactly is leaking.

  • on your winxp machine open windbg and attach to the client process(let it run for a while to magnify the problem, i.e. the memory leak)

  • at the prompt type

If using .NET 2/3.5
.loadby sos mscorwks
If using .NET 4 
.loadby sos clr

  • then run

!dumpheap -stat

you'll get a list of all the objects in memory grouped by class. look for the ones that have the most number of instances. Hopefully that will give you an indication of what is the offending code.

other options are:

!dumpheap -stat -type MyClass*

this will show you only instances of classes that start with MyClass.

Do not close windbg before detaching from the process otherwise it will kill your process.

这篇关于在XP C#WCF客户端内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆