我有一个问题,那就是使用C#的Timers.Timer类.考虑到以下大体轮廓:

1-回调是否在对象本身的上下文中运行,这样我就可以只使用成员变量(不像C++那样,您必须传递对象指针)?

class A {
  Timer m_Timer;
  int m_JustForShow;

  public void TimerHandler(Object stateinfo) {
    // is this right?
    string id=(string) stateinfo;
    // use id to check if action has completed and if not
    // we cancel it.
    if (m_JustForShow==1) {
      // Is this running under the objects context and I can just do this?
    }
  }

  public void MyEventNotification(in MyEventInfo ei)
  {
    if (ei.State!=MyEventState.Completed) {
      m_Timer=new Timer(TimerHandler, new ei.StringID, 1000, Timeout.Infinite);
    }
  }
}

推荐答案

是的,计时器在线程池中运行,而不是在对象上运行.正因为如此,通常的最佳实践是利用锁来确保在激发回调方法的同时不会有其他东西在修改您的对象.

readonly object m_Lock = new object();

  public void TimerHandler(Object stateinfo) {
    string id = (string)stateinfo;

    // Use lock to ensure thread safety when accessing shared resources
    lock (m_Lock) {
      if (m_JustForShow == 1) {
        // Perform actions using m_JustForShow
      }
    }
  }

这还将防止两个回调线程执行相同的代码.如果您的代码计算非常繁重,而计时器又非常快,那么在第一个回调完成之前,您可能会有多个回调.如果有可能,您可以增强锁,使线程超时,以避免过度等待/排队.使用过多的锁可能会导致性能问题.

Csharp相关问答推荐

Rx.Net -当关闭序列被触发时如何聚合消息并发出中间输出?

使用其可能实现的基类和接口的属性的方法

更改对象的旋转方向

并行令牌更新

Entity Framework Core 8 dbcontext—无法以多对多关系添加某些行'

安装附加的. exe与Visual Studio

如何使用XmlSerializer反序列化字符串数组?

Rx.Net窗口内部可观测数据提前完成

如何使用自定义负载均衡器管理Ocelot负载均衡器中的多线程和批读取

C#中浮点数的System.Text.Json序列化问题

N层解决方案上的依赖注入-删除样板

为什么我在使用有效令牌的情况下仍未获授权?

如何解决System.StackOverflowException:抛出System.StackOverflowException类型的异常.&# 39;生成随机代码时发生异常?

如何在单击按钮后多次异步更新标签

RavenDb:为什么在字符串==空的情况下过滤会过滤得太多?

如何对正方形格线进行对角分组

使用生产环境调试我的应用程序的快速方法

CsvHelper在第二次迭代时抛出System.ObjectDisposedException

为什么我不能在固定语句中使用外部函数?

将带有嵌套If-Else的Foreach循环转换为Linq表达式