SynchronizationContext上的回调

时间:2016-08-05 06:14:49

标签: c# .net wcf windowsformshost

试图解决为什么实现回调的Windows窗体无法正常工作。

我想做的事情:

  • 按下按钮并调用服务。
  • 服务回调表单(函数具有IsOneWay = true)
  • 表单相应地更新GUI

将UseSynchronizationContext设为false并在GUI成员上调用Invoke可以正常工作:

[CallbackBehavior(UseSynchronizationContext = false)]
public class DeliveryClient : System.Windows.Forms.Form, ICallback
{        
        public void ServiceCallback(string system, string state, string extraInfo)
        {
            if (state == "start")
            {
                Invoke((MethodInvoker)delegate { picBox.Visible = true; });
            }
            else
            {
                Invoke((MethodInvoker)delegate { picBox.Visible = false; });
            }
        }
}

但是UseSynchronizationContext = true并且直接调用成员不会:

[CallbackBehavior(UseSynchronizationContext = true)]
public class DeliveryClient : System.Windows.Forms.Form, ICallback
{        
        public void ServiceCallback(string system, string state, string extraInfo)
        {
            if (state == "start")
            {
                picBox.Visible = true;
            }
            else
            {
                picBox.Visible = false;
            }
        }

也没有按字面意思使用SyynchronizationContext

SynchronizationContext.Current.Send(_=> picBox.Visible = true, null);

第二版和第三版是否也有效?回调称为OneWay,因此服务在回调后继续。

1 个答案:

答案 0 :(得分:1)

您的Form是否真的是WCF服务客户端回调的实现,正如WCF所知(即不仅仅是您从WCF委托的内容)客户)?如果没有,那么您已将[CallbackBehavior]属性放在错误的位置。正如文档所述:

  

必须将CallbackBehaviorAttribute应用于实现回调协定的类

如果是你的客户回调的实现,那么没有好Minimal, Complete, and Verifiable code example我害怕我不能说出为什么该属性没有预期的效果。但我能够说,如果情况确实如此,那么你的代码设计得很糟糕。将您的UI与服务客户端回调实现相结合违反了许多针对健康代码的OOP原则,但最重要的是Separation of Concerns原则。

就此而言:

SynchronizationContext.Current.Send(_=> picBox.Visible = true, null);

那不是你应该如何使用SynchronizationContextCurrent属性返回当前运行的线程的上下文。当您需要致电Send()时,检索上下文为时已晚。您需要在创建对象时存储SynchronizationContext.Current,在您希望Send()调用委托的线程中执行(当然,该线程必须具有有用的上下文,例如在Winforms程序的主要UI线程。)

如果上述内容没有为您提供足够的信息以使您的代码正常工作,请通过提供可靠地重现问题的良好MCVE来改进问题。