我正在使用WPF GUI(使用MVVM)来控制嵌入式设备。到目前为止,该设备仍在开发中,目前无法可靠运行。因此,我创建了以下伪造设备:
interface IConnection
{
bool IsValid { get; }
bool Open();
void Close();
void Write(string message);
}
class SerialConnection : IConnection
{
// Not yet implemented
}
class DevConnection : IConnection
{
Timer _timer;
Action<string> _callback;
public bool IsValid {...}
public DevConnection(Action<string> callback)
{
_timer = new Timer(tick, null, Timeout.Infinite, Timeout.Infinite);
_callback = callback;
}
public bool Open() {...}
public void Close() {...}
public void Write(string Message) {...}
private void tick(object args)
{
_callback("V01" + ToHex(vol1) + "\n");
...
}
}
的
Action<string> _callback;
是使用我的模型来读取连接的有效载荷,并适当地更新其状态的功能
class Model
{
IConnection _connection;
public Model()
{
_connection = new DevConnection(Message);
}
private void Message(string payload)
{
...
_volume1 = floatValue;
...
}
}
但是,当创建模型时,在调用Model.IConnection.Open()启动计时器之前,我会在其他地方更改一堆属性。每次调用Message()回调时,调试器都会将模型显示为仍处于其原始的构造状态。
1)这里的幕后发生了什么?Threading.Timer是否正在为其计数/滴答执行创建新线程?如果是这样,为什么要创建我的Model类的默认副本?
2)如何解决?我什至尝试给DevConnection我的Model类的副本以直接对其进行操作(不是我想要的架构设置方式),但仍然导致相同的不良行为
不幸的是,我对线程理论只有基本的了解,却不知道如何在C#中实现它。可悲的是,我怀疑此问题是线程管理不当的结果。
鉴于神秘的“Model
班级额外副本”问题已解决。仍然存在如何从计时器计划的回调中安全更新UI的问题。
正如@Frank J所提到的,您的回调将在线程池线程上调用,而仅允许从UI线程的上下文中更新UI元素。这意味着,Message
如果直接或间接更新UI元素,则需要将在方法中执行的回调操作编组到UI线程上下文。
下面的代码段显示了一种实现方法。
class Model
{
private readonly SynchronizationContext _synchronizationContext;
private readonly IConnection _connection;
public Model()
{
// Capture UI synchronization context.
// Note: this assumes that Model is constructed on the UI thread.
_synchronizationContext = SynchronizationContext.Current;
_connection = new DevConnection(MessageCallback);
}
private void MessageCallback(string payload)
{
// schedule UI update on the UI thread.
_synchronizationContext.Post(
new SendOrPostCallback(ctx => Message(payload)),
null);
}
private void Message(string payload)
{
...
_volume1 = floatValue;
...
}
}
还有一条建议:我认为IConnection
应该是这样,IDisposable
因为您将不得不在某个地方处置计时器。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句