C# 将System.Threading.Timer对象引用传递给其回调函数
是否可以将System.Threading.Timer对象引用传递给其回调函数,如下所示:C# 将System.Threading.Timer对象引用传递给其回调函数,c#,.net,timer,C#,.net,Timer,是否可以将System.Threading.Timer对象引用传递给其回调函数,如下所示: System.Threading.Timer myTimer = new System.Threading.Timer(new TimerCallback(DoSomething), myTimer, 2000, Timeout.Infinite); 因为在“DoSomething”方法中,我想调用: myTimer.Change(5000, Timeout.Infinite); 我将在下面粘贴一个草
System.Threading.Timer myTimer = new System.Threading.Timer(new TimerCallback(DoSomething), myTimer, 2000, Timeout.Infinite);
因为在“DoSomething”方法中,我想调用:
myTimer.Change(5000, Timeout.Infinite);
我将在下面粘贴一个草稿控制台应用程序。
想法是这样的:我有一个计时器列表。每个计时器都会发出一些请求,当它收到请求时,它会更改一些共享数据。
但是,我不能将对计时器的引用传递到它的回调中,也不能使用它的索引,因为出于某种原因(调查)
使用系统;
使用System.Collections.Generic;
使用系统线程;
命名空间TimersInThreads
{
班级计划
{
公共静态int-shareddaint;
静态私有只读对象lockObject=新对象();
公共静态列表计时器=新列表();
静态void Main(字符串[]参数)
{
System.Threading.Timer Timer=new System.Threading.Timer(new timerrcallback(DoSomething),timers.Count-12000,Timeout.Infinite);
定时器。添加(定时器);
System.Threading.Timer timer2=新的System.Threading.Timer(新的TimerCallback(DoSomething),timers.Count-12000,Timeout.Infinite);
timers.Add(timer2);
System.Threading.Timer timer3=新的System.Threading.Timer(新的TimerCallback(DoSomething),timers.Count-12000,Timeout.Infinite);
定时器。添加(定时器3);
//定时器=新系统.Threading.timer(新定时器回调(DoSomething),“定时器1”,1000,Timeout.Infinite);
//timer=新系统.Threading.timer(新timer回调(DoSomething),“timer 2”,450,Timeout.Infinite);
//timer=新系统.Threading.timer(新timer回调(DoSomething),“timer 3”,1500,Timeout.Infinite);
Console.ReadLine();
}
静态空隙剂量测量(对象时间索引)
{
//请求
//得到回应
var x=getSomeNumberWithDelay();
//在收到响应后执行
锁定(锁定对象)
{
sharedDataInt++;
Console.WriteLine(“Timer”+(int)timerIndex+”,SharedTaint:“+SharedTaint+”\t\t”+DateTime.Now.ToString(“HH:mm:ss tt”)+“+DateTime.Now.毫秒.ToString()”;
}
计时器[(int)timerIndex].Change(5000,Timeout.Infinite);
}
静态int getSomeNumberWithDelay()
{
睡眠(5000);
返回3;
}
}
}
请给我一些想法或建议。
非常感谢,谢谢 将每次出现的
timers.Count-1
替换为timers.Count
:
System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(DoSomething), timers.Count, 2000, Timeout.Infinite);
timers.Add(timer);
将第一个计时器添加到列表时,列表中没有元素,因此timers.Count
等于0
另一种方法是将特定计时器的实例作为回调的第二个参数传递,而不是其索引。中的
状态
参数作为参数传递给TimerCallback
-这只是一个对象
,因此可以处理任何事情,包括计时器引用本身
所以
这是完全可以接受的。在回调中,您只需要将参数强制转换为Timer
static void DoSomething(object state)
{
...
var timer = (System.Threading.Timer)state;
}
再看看你的问题,我知道你要做的是把定时器作为参数传递到它的构造函数中(这显然是不可能的,因为它还没有被正式声明)。不过,您可以通过显式地将计时器传递给回调来解决这个问题
Timer t = null;
t = new Timer(delegate { DoSomething(t); }, null, 2000, Timeout.Infinite);
在触发回调时,
t
将设置为计时器的引用。我有一个用于此目的的类。它提供了一个带有状态的TypedCallback和对计时器的引用。该类维护引用列表并提供处理
我没有足够的“分数”来发表评论,但我还想指出,在James的回答中,您需要确保保留对计时器的引用。正如文档所述,即使仍在运行,它们也可能成为垃圾
/// <summary>
/// Holds a list of references to Timers; and provides typed objects to reference the Timer and its
/// State from within a TypedCallback. Synchronized. Usage:
/// <code>
/// TypedStateTimers myTimers = new TypedStateTimers(3);
/// public void MyMethod() {
/// typedStateTimers.Create("Hello, from Timer", new TypedCallback<string>((sr) => {
/// System.Console.WriteLine(sr.State); // "Hello, from Timer"
/// sr.Dispose(); // Invoke the StateRef method to ensure references are released
/// })).Start(1500, Timeout.Infinite);
/// }
/// </code>
/// </summary>
public class TypedStateTimers
{
/// <summary>
/// A typed delegate used as the callback when Timers are created.
/// </summary>
public delegate void TypedCallback<T>(StateRef<T> state);
/// <summary>
/// Wraps a Timer and State object to be used from within a TypedCallback.
/// </summary>
public class StateRef<T> : IDisposable
{
/// <summary>The state passed into TypedStateTimers.Create. May be null.</summary>
public T State { get; internal set; }
/// <summary>The Timer: initially not started. Not null.</summary>
public System.Threading.Timer Timer { get; internal set; }
/// <summary>The TypedStateTimers instance that created this object. Not null.</summary>
public TypedStateTimers Parent { get; internal set; }
/// <summary>
/// A reference to this object is retained; and then Timer's dueTime and period are changed
/// to the arguments.
/// </summary>
public void Start(int dueTime, int period) {
lock (Parent.Treelock) {
Parent.Add(this);
Timer.Change(dueTime, period);
}
}
/// <summary>Disposes the Timer; and releases references to Timer, State, and this object.</summary>
public void Dispose() {
lock (Parent.Treelock) {
if (Timer == null) return;
Timer.Dispose();
Timer = null;
State = default(T);
Parent.Remove(this);
}
}
}
internal readonly object Treelock = new object();
private readonly List<IDisposable> stateRefs;
/// <summary>
/// Constructs an instance with an internal List of StateRef references set to the initialCapacity.
/// </summary>
public TypedStateTimers(int initialCapacity) {
stateRefs = new List<IDisposable>(initialCapacity);
}
/// <summary>Invoked by the StateRef to add it to our List. Not Synchronized.</summary>
internal void Add<T>(StateRef<T> stateRef) {
stateRefs.Add(stateRef);
}
/// <summary>Invoked by the StateRef to remove it from our List. Not synchronized.</summary>
internal void Remove<T>(StateRef<T> stateRef) {
stateRefs.Remove(stateRef);
}
/// <summary>
/// Creates a new StateRef object containing state and a new Timer that will use the callback and state.
/// The Timer will initially not be started. The returned object will be passed into the callback as its
/// argument. Start the Timer by invoking StateRef.Start. Dispose the Timer, and release references to it,
/// state, and the StateRef by invoking StateRef.Dispose. No references are held on the Timer, state or
/// the StateRef until StateRef.Start is invoked. See the class documentation for a usage example.
/// </summary>
public StateRef<T> Create<T>(T state, TypedCallback<T> callback) {
StateRef<T> stateRef = new StateRef<T>();
stateRef.Parent = this;
stateRef.State = state;
stateRef.Timer = new System.Threading.Timer(
new TimerCallback((s) => { callback.Invoke((StateRef<T>) s); }),
stateRef, Timeout.Infinite, Timeout.Infinite);
return stateRef;
}
/// <summary>Disposes all current StateRef instances; and releases all references.</summary>
public void DisposeAll() {
lock (Treelock) {
IDisposable[] refs = stateRefs.ToArray();
foreach (IDisposable stateRef in refs) stateRef.Dispose();
}
}
}
//
///保存计时器的引用列表;并提供类型化对象以引用计时器及其
///类型回调中的状态。同步的。用法:
///
///TypedStateTimers myTimers=新的TypedStateTimers(3);
///公共方法(){
///typedStateTimers.Create(“你好,来自计时器”),新建TypedCallback((sr)=>{
///System.Console.WriteLine(sr.State);/“您好,来自计时器”
///sr.Dispose();//调用StateRef方法以确保释放引用
///}.Start(1500,Timeout.Infinite);
/// }
///
///
公共类TypedStateTimers
{
///
///创建计时器时用作回调的类型化委托。
///
公共委托无效类型回调(StateRef状态);
///
///包装要从TypedCallback中使用的计时器和状态对象。
///
公共类StateRef:IDisposable
{
///传递到TypedStateTimers.Create.的状态可能为null。
公共T状态{get;内部集;}
///计时器:最初未启动。不为空。
public System.Threading.Timer{get;内部设置;}
///创建此对象的TypedStateTimers实例。不为null。
公共类型StateTimers父项{get;internal set;}
///
///保留对此对象的引用;然后更改计时器的时间和周期
///对论点的反驳。
///
公共作废开始(整数段时间,整数段时间){
锁(Parent.Treelock){
父项。添加(此项);
计时器。更改(时间、周期);
}
}
///处置计时器;并释放对计时器、状态和此对象的引用。
公共空间处置(){
锁(Parent.Treelock){
if(Timer==null)返回;
Timer.Dispose();
定时器=空;
Timer t = null;
t = new Timer(delegate { DoSomething(t); }, null, 2000, Timeout.Infinite);
/// <summary>
/// Holds a list of references to Timers; and provides typed objects to reference the Timer and its
/// State from within a TypedCallback. Synchronized. Usage:
/// <code>
/// TypedStateTimers myTimers = new TypedStateTimers(3);
/// public void MyMethod() {
/// typedStateTimers.Create("Hello, from Timer", new TypedCallback<string>((sr) => {
/// System.Console.WriteLine(sr.State); // "Hello, from Timer"
/// sr.Dispose(); // Invoke the StateRef method to ensure references are released
/// })).Start(1500, Timeout.Infinite);
/// }
/// </code>
/// </summary>
public class TypedStateTimers
{
/// <summary>
/// A typed delegate used as the callback when Timers are created.
/// </summary>
public delegate void TypedCallback<T>(StateRef<T> state);
/// <summary>
/// Wraps a Timer and State object to be used from within a TypedCallback.
/// </summary>
public class StateRef<T> : IDisposable
{
/// <summary>The state passed into TypedStateTimers.Create. May be null.</summary>
public T State { get; internal set; }
/// <summary>The Timer: initially not started. Not null.</summary>
public System.Threading.Timer Timer { get; internal set; }
/// <summary>The TypedStateTimers instance that created this object. Not null.</summary>
public TypedStateTimers Parent { get; internal set; }
/// <summary>
/// A reference to this object is retained; and then Timer's dueTime and period are changed
/// to the arguments.
/// </summary>
public void Start(int dueTime, int period) {
lock (Parent.Treelock) {
Parent.Add(this);
Timer.Change(dueTime, period);
}
}
/// <summary>Disposes the Timer; and releases references to Timer, State, and this object.</summary>
public void Dispose() {
lock (Parent.Treelock) {
if (Timer == null) return;
Timer.Dispose();
Timer = null;
State = default(T);
Parent.Remove(this);
}
}
}
internal readonly object Treelock = new object();
private readonly List<IDisposable> stateRefs;
/// <summary>
/// Constructs an instance with an internal List of StateRef references set to the initialCapacity.
/// </summary>
public TypedStateTimers(int initialCapacity) {
stateRefs = new List<IDisposable>(initialCapacity);
}
/// <summary>Invoked by the StateRef to add it to our List. Not Synchronized.</summary>
internal void Add<T>(StateRef<T> stateRef) {
stateRefs.Add(stateRef);
}
/// <summary>Invoked by the StateRef to remove it from our List. Not synchronized.</summary>
internal void Remove<T>(StateRef<T> stateRef) {
stateRefs.Remove(stateRef);
}
/// <summary>
/// Creates a new StateRef object containing state and a new Timer that will use the callback and state.
/// The Timer will initially not be started. The returned object will be passed into the callback as its
/// argument. Start the Timer by invoking StateRef.Start. Dispose the Timer, and release references to it,
/// state, and the StateRef by invoking StateRef.Dispose. No references are held on the Timer, state or
/// the StateRef until StateRef.Start is invoked. See the class documentation for a usage example.
/// </summary>
public StateRef<T> Create<T>(T state, TypedCallback<T> callback) {
StateRef<T> stateRef = new StateRef<T>();
stateRef.Parent = this;
stateRef.State = state;
stateRef.Timer = new System.Threading.Timer(
new TimerCallback((s) => { callback.Invoke((StateRef<T>) s); }),
stateRef, Timeout.Infinite, Timeout.Infinite);
return stateRef;
}
/// <summary>Disposes all current StateRef instances; and releases all references.</summary>
public void DisposeAll() {
lock (Treelock) {
IDisposable[] refs = stateRefs.ToArray();
foreach (IDisposable stateRef in refs) stateRef.Dispose();
}
}
}