SynchronizationContext上的回调



试图弄清楚为什么实现回调的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,因此服务在回调后继续。

您的Form真的是WCF服务客户端回调的实现吗,正如WCF所知(即不仅仅是您从WCF客户端委托的东西)?如果没有,则说明[CallbackBehavior]属性放错了位置。正如文件所述:

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

如果它是客户端回调的实现,那么如果没有一个好的Minimal、Complete和Verifible代码示例,我恐怕无法说明为什么该属性没有达到预期效果。但我可以说,如果真的是这样的话,你的代码设计得很糟糕。将UI与服务客户端回调实现相结合违反了健康代码的许多OOP原则,但最重要的是违反了关注点分离原则。

就目前而言:

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

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

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

相关内容

  • 没有找到相关文章

最新更新