如何解决WPF:如何将数据从另一个域封送给用户控制
| 我必须使用另一个应用程序域中的功能。结果应显示在用户控件中。 我有这样的事情:var instance = domain.CreateInstanceFromAndUnwrap(...);
instance.Foo(myWpfUserControl as ICallback);
Foo(ICallback itf) {
itf.SetData(\"...\");
}
WpfUserControl.SetData(string data)
{
if (!dispatcher.CheckAccess())
dispatcher.Invoke(...)
...
}
我不得不将[Serializable]属性放到WpfUserControll类上,并实现序列化构造函数以及ISerializable接口,但是现在我收到异常:
The calling thread must be STA because many UI components require this
从UserControl()构造函数引发的
我应该怎么做才能避免这种情况?
先感谢您 !
=============================
解
正如@Al所注意到的,涉及跨应用程序域调用时,我的用户控件必须进行序列化。现在,我通过代理,该代理实现了ICallback接口。代理已标记为Serializable属性。
代理实现应该完全不了解用户控件,因为应该尝试再次反序列化用户控件实例。当我尝试通过界面从用户控件中抽象代理时,它没有帮助。当我尝试将接口传递给代理(由用户控件实现)时,发生了相同的异常。
最后,我将代理和用户控制与队列/信号灯分离了。队列由工作线程监控,该线程将对用户控件的调用
ps。此队列应继承自“ MarshalByObjectRef \”。
解决方法
如果异常来自构造函数,则意味着您不是从UI线程创建此控件实例。这样做可以,但是您必须通过在线程启动之前在线程对象上调用
.SetApartmentState(ApartmentState.STA)
来确保该线程是STA线程。
这也意味着您必须在线程对象启动之前对其进行访问,因此您不能在线程池线程上执行此操作。
最好的避免问题的方法可能是在主UI线程上创建控件,然后使用Dispatcher(或UiScheduler上的Task)分配Text值。这样,如果主线程需要设置,获取或绑定到控件,您还将避免出现问题,因为如果控件是在另一个线程上创建的,那将导致跨线程异常
如果可能,我建议您不要以这种方式对控件进行序列化。这样做将生成一个未绑定到任何面板或某些面板的新对象,并且原始控件也不会更新。遗憾的是,您不能继承MarshalByRefObject,因为序列化只会将引用传递给其他域,因此会消除序列化。
如果可以,请分别调用Foo,然后将结果传递到原始Appdomain中的SetData
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。