调度程序开始调用方法,几分钟后停止调用委托的方法
本文关键字:方法 调用 几分钟 分钟 开始 调度程序 | 更新日期: 2023-09-27 18:08:02
>我正在使用 WPF 使用 C# 构建一个应用程序,该应用程序需要不断订阅由第三方服务器生成的事件,并根据收到的事件更新 UI 控件,最初我需要先连接到服务器才能发出事件,连接是一项昂贵的操作,所以我将该线程放在单独的线程上,并使用了 WPF 调度程序 BeginInVoke 和一个委托订阅事件的方法,现在的问题是这在我运行应用程序后的一段时间内可以正常工作,我的意思是 UI 控件将在停止接收通知之前通知一段时间,我尝试放置停止点并单步进入代码,委托调用的方法没有被调度程序调用,第三方服务器正在继续发出事件,但我的调度程序没有再次拿起它,我已经尝试了所有可能的方法,但我找不到任何解决方案,任何有帮助和解决方案的人都将不胜感激
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);
}
}}
侦听器可能正在引发异常。您不会知道它,因为我怀疑您没有调用 EndInvoke 将异常重新加入主线程。
将您的代码更改为以下内容:
Action action = () => ... ;
action.BeginInvoke(action.EndInvoke, null);
当服务现在失败时,你将在主线程上收到异常,并可以通过查看堆栈跟踪来确定导致异常的原因。
编辑
这不应该是必需的,因为您实际上使用的是在 UI 线程上运行Dispatcher.BeginInvoke
。
我建议添加一些日志记录,并尝试在启用首次机会例外的情况下在Visual Studio中进行调试。
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");
一种可能性是FreeSwitch
模块实际上是将处理程序传递给非托管代码。在这种情况下,GC 不会知道委托实际上是可访问的,并且会收集它。您可以通过创建一个成员字段来存储event_handler
委托来测试此理论:
_newEventDelegateMember = new ProperDelegateType(event_handler);
event_bind = FreeSWITCH.EventBinding.Bind("SampleClient",
switch_event_types_t.SWITCH_EVENT_ALL, null,
**_newEventDelegateMember**, true);