SynchronizationContext 的回调

Callbacks on SynchronizationContext

想弄清楚为什么 windows 实现回调的表单不起作用。

我想做什么:

将 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;
            }
        }

字面上使用 SynchronizationContext 也不行

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

第二个和第三个版本应该也可以吗?回调称为 OneWay,因此服务在回调后继续。

你的Formclass真的你的WCF服务客户端回调的实现吗,正如WCF所知(即不仅仅是您从 WCF 客户端委托给的东西)?如果不是,那么您将 [CallbackBehavior] 属性放在了错误的位置。正如文档所述:

The CallbackBehaviorAttribute must be applied to the class that implements the callback contract

如果是执行你的客户端回调,那么就没有好的Minimal, Complete, and Verifiable code example I'm afraid I wouldn't be able to say why the attribute isn't having the expected effect. But I would be able to say that, if that is indeed the case, your code is designed poorly. Combining your UI with your service client callback implementation violates a number of OOP principles for healthy code, but most importantly the Separation of Concerns原则。

就此而言:

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

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

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