我使用线程从我的程序连接到多个客户端(PLC)。程序将发送数据并接收来自PLC的响应。我遇到的问题是,在调试模式下,time..the程序的一个步骤(切换断点)工作正常!,接收到的ID确认它来自其中一个线程。但是,如果我只是在不切换任何断点的情况下进行调试,响应事件将收到相同的ID,尽管在不同的线程上。有什么不对的..。
带有断点的调试模式:
没有断点的调试模式:
下面是我的代码
启动请求:
private void StartRequest()
{
foreach (ModbusTCP work in works)
{
work.Connect();
Thread.Sleep(1000);
if (work.Connected)
{
try
{
Thread thread = new Thread(new ThreadStart(() => work.StartReadHoldingRegister())) {
Name = ((ReadHoldingRegisterParam)work.SetReadHoldingRegisterParam).id.ToString(),
IsBackground = true
};
work.OnResponseEvent += new EventHandler<ModbusTCP.ResponseEventArgs>(modbus_OnResponseEvent);
work.OnExceptionEvent += new EventHandler<ModbusTCP.ExceptionEventArgs>(modbus_OnExceptionEvent);
thread.Start();
threads.Add(thread);
}
catch (ThreadStateException ex)
{
MessageBox.Show(ex.Message);
}
}
else
work.Disconnect();
}
}
响应事件
private void modbus_OnResponseEvent(object sender, ModbusTCP.ResponseEventArgs e)
{
lock (lockingObject)
{
if (e.data.Length > 0)
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
AddRow(RcvDataGrid, new PLCPacket() {
PLCId = e.id.ToString(),
PLCIp = "Test",
PLCTime = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt"),
PLCData = ""
});
}));
}
}
}
发布于 2016-06-02 07:40:51
变量work
在线程之间共享。一旦执行了一个线程,它就会接受变量work
的任何值。这取决于每个线程处理的速度。当您使用调试器执行代码时,您不会体验到这一点。
如果在匿名方法之前捕获值,则应该可以:
try
{
// capture the current value of the loop variable
ModbusTCP localWork = work;
// so the anonymous method uses the reference in localWork
// instead of whatever value work has, which can be anywhere
// the future, worst case after your loop is finished, where
// work would hold the last value of the loop, and then
// start all threads with that value.
Thread thread = new Thread(
new ThreadStart(
() => localWork.StartReadHoldingRegister()))
{
Name = ((ReadHoldingRegisterParam) localWork.SetReadHoldingRegisterParam).id.ToString(),
IsBackground = true };
});
localWork.OnResponseEvent += new EventHandler<ModbusTCP.ResponseEventArgs>(modbus_OnResponseEvent);
localWork.OnExceptionEvent += new EventHandler<ModbusTCP.ExceptionEventArgs>(modbus_OnExceptionEvent);
发布于 2016-06-02 08:37:58
一项附带意见:
lock (lockingObject)
{
if (e.data.Length > 0)
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
这个代码不太可能是正确的。在这里,您将在原始线程中获得一个锁,然后提交一个新的操作--异步。锁的作用域为当前方法,因此在BeginInvoke
调用返回时将立即释放,而不是在操作本身期间释放。真正由锁保护的唯一操作是e.data.Length
检查,它在参数(非共享)状态下操作,因此不需要保护。
在操作中放置锁可能更有意义,但是操作总是在主线程上执行,因此不太可能真正需要保护(因为基本上是单线程的)。很难准确地猜出您想要实现的目标是什么,看到整个代码,但是lock(lockingObject)
并不是必要的,也不太有用。
https://stackoverflow.com/questions/37585229
复制相似问题