1

我希望我能正确地用这个词。我有一个正在使用的 WCF 服务(双工通道通信),其中一个客户端向该服务注册。服务的注册方法返回一个值。我希望被调用的服务注册方法的方法也调用将发送客户端注册通知的回调方法(我有我的原因,在这里解释只会混淆问题)。问题是客户端实现的回调必须在主应用程序线程中运行才能正常工作(主要是由于与第三方应用程序的集成)。服务注册方法调用也发生在同一个线程中,所以它有效地锁定了,因为客户端正在寻找从服务注册方法返回到线程,从而阻止回调方法能够运行。如果我告诉它为刚刚注册的上下文之外的所有上下文调用所有回调方法,它就可以正常工作。但是如果我告诉它包含它,显然它会锁定,因为该线程已经被锁定。我可以将 UseSynchronizationContext 的回调属性属性设置为 false,但这意味着回调方法是在与主线程不同的线程上调用的,现在程序的其余部分将无法工作。任何帮助将不胜感激。显然它被锁定了,因为该线程已经被锁定了。我可以将 UseSynchronizationContext 的回调属性属性设置为 false,但这意味着回调方法是在与主线程不同的线程上调用的,现在程序的其余部分将无法工作。任何帮助将不胜感激。显然它被锁定了,因为该线程已经被锁定了。我可以将 UseSynchronizationContext 的回调属性属性设置为 false,但这意味着回调方法是在与主线程不同的线程上调用的,现在程序的其余部分将无法工作。任何帮助将不胜感激。

这基本上是注册方法(初稿..)

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
                    UseSynchronizationContext = false,
                    ConcurrencyMode = ConcurrencyMode.Multiple,
                    Namespace = "http://MyApp/Design/CADServiceTypeLibrary/2012/12")]
    public class DTOTransactionService : IDTOTransactionService, IDisposable
    {
             //some more stuff

public CADManager RegisterCADManager(int processID, bool subscribeToMessages)
        {

            List<CADManager> cadMgrs = this.CADManagers;

            bool registered = false;

            //Create new CADManager mapped to process id
            CADManager regCADManager = new CADManager(processID);

            //Add to CADManagers List and subscribe to messages
            if (regCADManager.IsInitialized)
            {
                cadMgrs.Add(regCADManager);
                this.CADManagers = cadMgrs;

                //Subscribe to callbacks
                if (subscribeToMessages)
                    SubscribeCallBack(regCADManager.ID);

                registered = true;
            }

            //Send registration change notification
            RegistrationState state;
            if (registered)
                state = RegistrationState.Registered;
            else
                state = RegistrationState.RegistrationException;

            foreach (CallBackSubscriber subscriber in this.CallBackSubscribers)
            {
                    subscriber.CallBackProxy.CADManagerRegistrationNotification(regCADManager.ID, state);
            }

            return regCADManager;
        }
}
4

1 回答 1

1

我想我已经弄清楚了。让我感到震惊的是,由于对服务方法的调用期望返回值,并且回调将与期望返回值的客户端方法在同一个线程中发生,这可能是死锁的结果,这让我感到震惊健康)状况。然后我决定尝试使用不同的线程调用服务中的回调方法来解决当前线程条件。换句话说,围绕其方法尚未从服务方法提供返回值的当前线程工作。有效!这是正确的方法吗?我有足够的经验在这里很危险,所以如果其他人的经验表明这是错误的处理方式,我会全神贯注。

        Thread notifyThread = new Thread(delegate()
        {
            foreach (CallBackSubscriber subscriber in this.CallBackSubscribers)
            {
                subscriber.CallBackProxy.CADManagerRegistrationNotification(regCADManager.ID, state);
            }
        });

更新:

是的,线程和死锁条件是问题所在,但是我最近发现的更合适的解决方法是使用 SynchronizationContext。要使用,请创建 SynchronizationContext 类型的属性或字段,然后在您希望使用 SynchronizationContext.Current 捕获的上下文中将值分配给字段/属性。然后,在 Service 调用的回调方法中使用 Post() 方法(通过 SendOrPostCallback 对象为其提供委托)。一个简短的例子:

  private SynchronizationContext _appSyncContext = null;

  private DTOCommunicationsService()
    {
        this.AppSyncContext = SynchronizationContext.Current;

        //Sets up the service proxy, etc, etc
        Open();
    }

  // Callback method
    public void ClientSubscriptionNotification(string clientID, SubscriptionState subscriptionState)
    {
        SendOrPostCallback callback = delegate(object state)
        {
            object[] inputArgs = (object[])state;
            string argClientID = (string)inputArgs[0];
            SubscriptionState argSubState = (SubscriptionState)inputArgs[1];

            //Do stuff with arguments

        };

        _appSyncContext.Post(callback, new object[] { clientID, subscriptionState });
    }
于 2013-05-01T23:39:53.537 回答