Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 我可以在其回调中处理Threading.Timer吗?_.net_Callback_Timer_Dispose - Fatal编程技术网

.net 我可以在其回调中处理Threading.Timer吗?

.net 我可以在其回调中处理Threading.Timer吗?,.net,callback,timer,dispose,.net,Callback,Timer,Dispose,我正在使用Threading.Timer,例如: new Timer(new TimerCallback(y=> { try { Save(Read(DateTime.Now)); // here i want to dispose this timer } catch { } }),null,100000,10000); 如何在回调中处理此计时器。还是变通

我正在使用
Threading.Timer
,例如:

new Timer(new TimerCallback(y=>
{
    try
    {
        Save(Read(DateTime.Now));
        // here i want to dispose this timer
    }
    catch
    {                          
    }
}),null,100000,10000);
如何在回调中处理此计时器。还是变通办法? 更新:让我解释一下情况。我想尝试调用“Save”方法,但它会引发异常。如果它能工作,我需要停止计时器。

试试这个:

Timer timer = null;
timer = new Timer(new TimerCallback(y =>
{    
    try    
    {
        Save(Read(DateTime.Now));        
        // here i want to dispose this timer
        timer.Dispose();    
    }    
    catch    
    {    
    }
}));
timer.Change(10000, 10000);

编辑:


根据Chuu的建议,我稍微修改了上面的代码。请注意,如果不同的计时器事件同时调用TimerCallback,
timer.Dispose
可能会被多次调用。幸运的是,
计时器
不关心它是否被多次处理。

您需要将计时器的引用保存在一个变量中-

public class MyClass
{
    private Timer _timer;

    public void StartTimer()
    {
        _timer =  new Timer(new TimerCallback(y=>{
                            try
                            {
                                Save(Read(DateTime.Now));
                                _timer.Dispose();
                            }
                            catch { 

                            }
                        }),null,100000,10000);
    }



}

注意:这是未经测试的代码。请检查它是否工作并更新。

您必须将对计时器的引用存储在某个位置,并将其作为状态传递给计时器对象本身。尝试创建类似以下内容的类:

public class TimerContainer
{
  public Timer Timer { get; set; }
}
然后在您的方法中使用它,如下所示:

Action<object> tcb = state =>
{
  var container = (TimerConatiner)state;
  try
  {
    Save(Read(DateTime.Now));
    container.Timer.Dispose();
  }
  catch
  {
    // whatever...
  }
};

var container = new TimerContainer();
container.Timer = new Timer(tcb, container, 100000, 10000);
Action tcb=state=>
{
var容器=(TimerConatiner)状态;
尝试
{
保存(读取(DateTime.Now));
container.Timer.Dispose();
}
抓住
{
//不管怎样。。。
}
};
var container=new TimerContainer();
container.Timer=新计时器(tcb,container,100000,10000);

这里有一个更好的方法。当您使用只有一个参数(TimerCallback)的构造函数时,传递给回调的状态将是计时器本身

Timer timer = new Timer(o =>
{
     ((Timer)o).Dispose();
     //Your code here     
});

//Start the timer
timer.Change(100000,10000);
以下是msdn文档中的一个示例:

public void StartTimer(int dueTime)
{
    Timer t = new Timer(new TimerCallback(TimerProc));
    t.Change(dueTime, 0);
}

private void TimerProc(object state)
{
    // The state object is the Timer object.
    Timer t = (Timer) state;
    t.Dispose();
    Console.WriteLine("The timer callback executes.");
}

如果使用多线程或多任务处理,请小心!如果是这样,下面是CancelAfter方法extensor(.net 4.0)的代码和解决方案:

private static object syncObj=new object();
public static void CancelAfter(此CancellationTokenSource源代码,int-timeout毫秒,操作代码=null)
{
if(timeoutmillizes==0)返回;//无超时
if(source==null)
{
抛出新的NullReferenceException();
}
如果(超时毫秒<-1)
{
抛出新ArgumentOutOfRangeException(“超时”);
}
计时器=新计时器(委托(对象自身)
{
锁(同步对象)
{
尝试
{
如果(空!=代码)
code.Invoke();
source.Cancel();
((IDisposable)self.Dispose();
}
捕获(ObjectDisposedException)
{
}                   
}
});
timer.Change(timeout毫秒,-1);
}
}
问候,,
Juanlu,ElGuerre

你有没有试过把它分配给一个变量,然后访问这个变量?为什么你不能简单地用
语句把
计时器
包装在
中呢?@Cody,因为计时器可能会比预期的更早被释放。哇,我想把这个问题弄得复杂一些。显而易见的解决方案确实是一个
Dispose
语句。我以为这已经被排除在“不可选项”之外了。我想这太明显了:-)我的损失,你的收获。我经常把事情弄得太复杂+我不认为这是100%线程安全的,理论上可能会发生以下一系列事件(不可思议地不太可能):1。计时器已创建。2.3.线程池4上的回调火。5.分配发生。线程安全的方法可能是创建具有无限超时的计时器,以在线程池回调之前强制赋值,然后使用Change()设置循环属性。@Chuu:这一点很好。我认为你是对的。我相应地改变了答案。
       private static object syncObj = new object();

       public static void CancelAfter(this CancellationTokenSource source, int timeoutMilliseconds, Action code = null)
    {
        if (timeoutMilliseconds == 0) return; // No timeout

        if (source == null)
        {
            throw new NullReferenceException();
        }
        if (timeoutMilliseconds < -1)
        {
            throw new ArgumentOutOfRangeException("timeout");
        }
        Timer timer = new Timer(delegate(object self)
        {
            lock (syncObj)
            {
                try
                {
                    if (null != code)
                        code.Invoke();
                    source.Cancel();

                    ((IDisposable)self).Dispose();
                }
                catch (ObjectDisposedException)
                {
                }                   
            }
        });
        timer.Change(timeoutMilliseconds, -1);
    }
}