C# 在一种情况下未执行Dispatcher.BeginInvoke

C# 在一种情况下未执行Dispatcher.BeginInvoke,c#,.net,multithreading,dispatcher,C#,.net,Multithreading,Dispatcher,我正在尝试修复现有应用程序中的一个bug,在单一情况下,没有执行已调度事件 在我们的应用程序中,有几个服务实现一个公共抽象类(AbstractService)。我遇到的问题发生在服务保存实体并且必须在UI线程中发出通知时 抽象服务的相关部分: public abstract class AbstractService<TEntity, TData, TInfo> : IDataProvider, IAbstractService where TEntity : Abstrac

我正在尝试修复现有应用程序中的一个bug,在单一情况下,没有执行已调度事件

在我们的应用程序中,有几个服务实现一个公共抽象类(AbstractService)。我遇到的问题发生在服务保存实体并且必须在UI线程中发出通知时

抽象服务的相关部分:

public abstract class AbstractService<TEntity, TData, TInfo> : IDataProvider, IAbstractService
    where TEntity : AbstractEntity, new()
    where TData : AbstractData<TEntity>
    where TInfo : IEntityInfo {

    [...]

    protected virtual void NotifyEntityChanged(NotifyEventItem<TInfo>[] pNotifyEventItems) { }

    private void NotifyPersPlanChanged() {
        if (PersPlanChanged != null)
            PersPlanChanged(this, new NotifyEventArgs<IEntityInfo>(null, PersistanceState.Reset));

        Debug.WriteLine(string.Format("{0} {1} Call {2} to NotifyPersPlanChanged",
            DateTime.Now.ToLongTimeString(), GetType().Name, m_counterNotifyPersPlanChanged++));
    }

    private static int m_counterInternalFireNotification;
    private void InternalFireNotification(List<NotifyEventItem<TInfo>> pNotifyEventItem) {
        if (pNotifyEventItem == null || pNotifyEventItem.Count == 0)
            return;

        Debug.WriteLine(string.Format("{0} {1} Call {2} to InternalFireNotification",
            DateTime.Now.ToLongTimeString(), GetType().Name, m_counterInternalFireNotification++));

        // do not call the event handlers directly, because a transaction may be in progress and
        // we want the event handlers to see the end results of the modifications.
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new HandleEntityChanged(NotifyEntityChanged), pNotifyEventItem.ToArray());
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new HandlePersPlanChanged(NotifyPersPlanChanged));
    }
}
所有服务的实例化如下所示:

WorkItem.RootWorkItem.Services.AddNew<ErgaenzungsfeldService, IErgaenzungsfeldService>();
WorkItem.RootWorkItem.Services.AddNew<DienstleistenderService, IDienstleistenderService>();
问题:是什么原因导致通知无法按说明执行

[Edit]通过存储
DispatcherOperation
,我获得了更多的见解:

private List<DispatcherOperation> m_dispatcherOperationresults = new List<DispatcherOperation>();
private void InternalFireNotification(List<NotifyEventItem<TInfo>> pNotifyEventItem) {
   if (pNotifyEventItem == null || pNotifyEventItem.Count == 0)
      return;

   m_log.DebugFormat("InternalFireNotification called for {0}. TInfo type is {1}", GetType(), typeof(TInfo));

   // do not call the event handlers directly, because a transaction may be in progress and
   // we want the event handlers to see the end results of the modifications.
   DispatcherOperation result = Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Send, new HandleEntityChanged(NotifyEntityChanged), pNotifyEventItem.ToArray());
   m_dispatcherOperationresults.Add(result);
   Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new HandlePersPlanChanged(NotifyPersPlanChanged));
}
private List m_dispatcherooperationresults=new List();
私有void InternalFireNotification(列表pNotifyEventItem){
如果(pNotifyEventItem==null | | pNotifyEventItem.Count==0)
返回;
DebugFormat(“为{0}调用的InternalFireNotification.TInfo类型为{1}”,GetType(),typeof(TInfo));
//不要直接调用事件处理程序,因为事务可能正在进行中,并且
//我们希望事件处理程序看到修改的最终结果。
DispatcherOperation结果=Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Send,新HandleEntityChanged(NotifyEntityChanged),pNotifyEventItem.ToArray());
m_dispatcherOperationresults.Add(结果);
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle,新HandlePersPlanChanged(NotifyPersPlanChanged));
}
这清楚地表明,委托执行被卡在执行队列中。无论DispatcherPriority是否设置为ApplicationIdle(一如既往)或Send(这是最高优先级),它们都会停留在ErgaenzungsfeldService

在此打印屏幕中,项目0-3在导入和挂起期间从非UI线程触发,而项目4从GUI线程触发(分钟后)并执行

问题:这些学员在为其他课程工作的同时,在某些课程上待决的原因是什么?

我的评论是“正式的”。这可能是由从另一个线程调用Dispatcher.CurrentDispatcher引起的。这可能会导致应用程序创建一个新的调度程序,该调度程序对UI没有任何访问权限


假设您正在从UI创建ErgaenzungsfeldService类,则可以创建值为Dispatcher.CurrentDispatcher的只读Dispatcher字段。这将为您提供UI调度程序。

您是否尝试过为BeginInvoke设置不同的优先级?应用程序对我来说很危险。此外,您可以使用返回的DispatcherOperation对象来测试dispatcher是否未如此处备注部分所述关闭:。是的,我关闭了,无论优先级如何,都不会调用dispatcher。我已将DispatcherOperations添加到列表中以进行调试。它们的状态保持为挂起状态,即使在分钟后,来自另一个类的状态也会被执行。您正在从另一个线程调用Dispatcher.CurrentDispatcher,对吗?这有时会创建一个新的调度程序,而该调度程序不是具有UI访问权限的调度程序@罗德里戈维多娃打得好!对于上面的示例,m_dispatcherOperationresults[0]。Dispatcher==m_dispatcherOperationresults[1]。Dispatcher为true,而m_dispatcherOperationresults[0]。Dispatcher==m_dispatcherOperationresults[4]。Dispatcher为false。现在我必须弄清楚要做什么来修复它。我仍然不明白为什么它适用于某些对象,但不适用于其他对象。我以前遇到过这种情况。假设您正在从UI创建ErgaenzungsfeldService类,则可以创建值为Dispatcher.CurrentDispatcher的只读Dispatcher字段。这将为您提供UI调度程序。我将接受您的回答,因为这将使我走上解决问题的正确轨道。事实证明,我说它对某些对象有效,但对其他对象无效的说法是错误的!在导入过程中,所有已调度事件都停留在导入线程的调度程序队列中,并且在导入触发其他对象的正确行为后,从UI线程手动触发事件:/
WorkItem.Services.Get<IDienstleistenderService>()

[ServiceDependency]
public IErgaenzungsfeldService ErgaenzungsfeldService { get; set; }
09:39:44 ErgaenzungsfeldService Call 0 to InternalFireNotification
09:39:44 ErgaenzungsfeldService Call 1 to InternalFireNotification
09:39:44 ErgaenzungsfeldService Call 2 to InternalFireNotification
09:39:44 ErgaenzungsfeldService Call 3 to InternalFireNotification
09:40:08 DienstleistenderService Call 0 to InternalFireNotification
09:40:08 DienstleistenderService Call 1 to InternalFireNotification
09:40:09 DienstleistenderService Call 2 to InternalFireNotification
[...]
09:40:14 DienstleistenderService Call 652 to InternalFireNotification
09:40:14 DienstleistenderService Call 653 to InternalFireNotification
09:40:14 DienstleistenderService Call 654 to InternalFireNotification
09:40:14 DienstleistenderService Call 655 to InternalFireNotification
09:40:14 AdaService Call 0 to InternalFireNotification
09:40:14 DienstleistenderService Call 656 to InternalFireNotification
09:40:14 DienstleistungService Call 0 to InternalFireNotification
09:40:14 AufbauorganisationService Call 0 to InternalFireNotification
09:40:14 AufbauorganisationService Call 1 to InternalFireNotification
09:40:14 AdaService Call 0 to NotifyPersPlanChanged
09:40:14 DienstleistenderService Call 0 to NotifyEntityChanged
09:40:16 DienstleistenderService Call 0 to NotifyPersPlanChanged
09:40:16 DienstleistungService Call 0 to NotifyPersPlanChanged
09:40:16 AufbauorganisationService Call 0 to NotifyPersPlanChanged
09:40:16 AufbauorganisationService Call 1 to NotifyPersPlanChanged
private List<DispatcherOperation> m_dispatcherOperationresults = new List<DispatcherOperation>();
private void InternalFireNotification(List<NotifyEventItem<TInfo>> pNotifyEventItem) {
   if (pNotifyEventItem == null || pNotifyEventItem.Count == 0)
      return;

   m_log.DebugFormat("InternalFireNotification called for {0}. TInfo type is {1}", GetType(), typeof(TInfo));

   // do not call the event handlers directly, because a transaction may be in progress and
   // we want the event handlers to see the end results of the modifications.
   DispatcherOperation result = Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Send, new HandleEntityChanged(NotifyEntityChanged), pNotifyEventItem.ToArray());
   m_dispatcherOperationresults.Add(result);
   Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new HandlePersPlanChanged(NotifyPersPlanChanged));
}