Reputation: 19
I am building an application with C# using WPF, the application needs to continually subscribe to an event that is generated by a third party server, and update the UI controls based on the received events,Initially I need to connect to the server before events can be issued out, the connection is an expensive operation so I put that one on a seperate thread and I used the WPF Dispatcher BeginInVoke and a delegate method to subscribe to the events, now the problem is this will work fine for sometime after I run the application, I mean the UI controls will be notified for some time before it stops recieving notification, I tried put stop point and stepped into the code, the method being called by the delegate is not being invoked by the dispatcher and the third party server is continuoslly issuing the events but my dispatcher doesnot pick it up again, I have tried all possible method, but I couldnot find any solution to it, anybody with help and solutions will be appreciated
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using System.Windows.Threading;
using System.Media;
using ClientPhone.Utility;
using System.Threading.Tasks;
using ClientPhone.Core.DAL;
using ClientPhone.Core.Model;
namespace ClientPhone.View
{
/// <summary>
/// Interaction logic for TestView.xaml
/// </summary>
public partial class TestView : Window
{
private FreeSwitchEventHandler _freeSwitchEventHandler;
private delegate void EventDelegate(switch_event evt);
public static NotificationInfo _notificationInfo;
private EventDelegate del;
public TestView()
{
InitializeComponent();
del = new EventDelegate(actual_event_handler);
ConnectToServer();
}
private void ConnectToServer()
{
string err = string.Empty ;
const uint flags = (uint)(switch_core_flag_enum_t.SCF_USE_SQL | switch_core_flag_enum_t.SCF_USE_AUTO_NAT);
freeswitch.switch_core_set_globals();/*Next 3 lines only needed if you want to bind to the initial event or xml config search loops */
freeswitch.switch_core_init(flags, switch_bool_t.SWITCH_FALSE, ref err);
IDisposable search_bind = FreeSWITCH.SwitchXmlSearchBinding.Bind(xml_search, switch_xml_section_enum_t.SWITCH_XML_SECTION_CONFIG);
event_bind = FreeSWITCH.EventBinding.Bind("SampleClient", switch_event_types_t.SWITCH_EVENT_ALL, null, event_handler, true);
}
private void event_handler(FreeSWITCH.EventBinding.EventBindingArgs args)
{
Dispatcher.BeginInvoke(del, DispatcherPriority.Send,new object[] { args.EventObj });
}
private void actual_event_handler(switch_event evt)
{
_eventInfo = _eventHandler.HandleEvents(evt);
if (_eventInfo != null && _eventInfo.Callee == _userId)
{
if ((!_callState.IsCallIncoming && _eventInfo.State!="hangup")&& _eventInfo.Caller!=null)
{
SetIsAnsweredParameters()
}
}
if (_eventInfo != null && (_eventInfo.ChannelState == "CS_DESTROY" || _eventInfo.ChannelState == "CS_HANGUP"))
{
ResetUIState();
}
}
private void SetIsAnsweredParameters()
{
if (!_isTimercounting)
{
_timerMinutes = 0;
_timerSeconds = 0;
_callState.IsCallActive = true;
_isTimercounting = true;
_soundManager.StopPlayer();
_timer.Interval = TimeSpan.FromSeconds(1);
_timer.Start();
grdNotification.Visibility = Visibility.Visible;
}
}
private void UpdateHistory(string call)
{
lstHistory.Items.Add(call);
}
} }
Upvotes: 0
Views: 3974
Reputation: 48596
One possibility is that the FreeSwitch
module is actually passing your handler to unmanaged code. In that case, the GC wouldn't know that the delegate is actually reachable and would collect it. You can test this theory by creating a member field to store the event_handler
delegate:
_newEventDelegateMember = new ProperDelegateType(event_handler);
event_bind = FreeSWITCH.EventBinding.Bind("SampleClient",
switch_event_types_t.SWITCH_EVENT_ALL, null,
**_newEventDelegateMember**, true);
Upvotes: 0
Reputation: 19220
The listener is probably throwing an exception. You won't know about it because I suspect you're not calling EndInvoke to rejoin the exception onto the main thread.
Change your code to this:
Action action = () => ... ;
action.BeginInvoke(action.EndInvoke, null);
When the service fails now, you'll get the exception on the main thread, and can work out what's causing it by viewing the stack trace.
Edit
This shouldn't be necessary as you are actually using Dispatcher.BeginInvoke
which runs on the UI thread anyway.
I suggest adding some logging, and also try debugging in Visual Studio with first chance exceptions enabled.
var op = Dispatcher.BeginInvoke(del, DispatcherPriority.Send,
new object[] { args.EventObj });
op.Completed += (s,e) => logger.Debug("Completed");
op.Aborted += (s,e) => logger.Debug("Aborted");
Upvotes: 1