首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >c#中线程模式的适当回调

c#中线程模式的适当回调
EN

Stack Overflow用户
提问于 2016-06-02 07:23:47
回答 2查看 73关注 0票数 3

我使用线程从我的程序连接到多个客户端(PLC)。程序将发送数据并接收来自PLC的响应。我遇到的问题是,在调试模式下,time..the程序的一个步骤(切换断点)工作正常!,接收到的ID确认它来自其中一个线程。但是,如果我只是在不切换任何断点的情况下进行调试,响应事件将收到相同的ID,尽管在不同的线程上。有什么不对的..。

带有断点的调试模式:

没有断点的调试模式:

下面是我的代码

启动请求:

代码语言:javascript
运行
复制
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();
    }            
}

响应事件

代码语言:javascript
运行
复制
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 = ""
                });
            }));
        }
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-02 07:40:51

变量work在线程之间共享。一旦执行了一个线程,它就会接受变量work的任何值。这取决于每个线程处理的速度。当您使用调试器执行代码时,您不会体验到这一点。

如果在匿名方法之前捕获值,则应该可以:

代码语言:javascript
运行
复制
 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);                                            
票数 4
EN

Stack Overflow用户

发布于 2016-06-02 08:37:58

一项附带意见:

代码语言:javascript
运行
复制
lock (lockingObject)
{
    if (e.data.Length > 0)
    {
        this.Dispatcher.BeginInvoke(new Action(() =>
        {

这个代码不太可能是正确的。在这里,您将在原始线程中获得一个锁,然后提交一个新的操作--异步。锁的作用域为当前方法,因此在BeginInvoke调用返回时将立即释放,而不是在操作本身期间释放。真正由锁保护的唯一操作是e.data.Length检查,它在参数(非共享)状态下操作,因此不需要保护。

在操作中放置锁可能更有意义,但是操作总是在主线程上执行,因此不太可能真正需要保护(因为基本上是单线程的)。很难准确地猜出您想要实现的目标是什么,看到整个代码,但是lock(lockingObject)并不是必要的,也不太有用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37585229

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档