【问题标题】:Async System.Threading.Timer sometimes throwing null exception [closed]Async System.Threading.Timer 有时会抛出空异常[关闭]
【发布时间】:2020-04-13 16:18:07
【问题描述】:

我正在尝试在一定时间间隔后异步执行代码,并且只想在完成代码执行后再次检查以防止重叠。为此,我使用以下变量和计时器代码。

private System.Threading.Timer _timer;
private int _intervalInMilliSec = 10000;

_timer = new System.Threading.Timer(async (o) =>
{
    // Stop the timer;
    _timer.Change(-1, -1);

    // awaited api call goes here

    // start timer again (BeginTime, Interval)
    _timer.Change(_intervalInMilliSec, _intervalInMilliSec);
}, null, 0, _intervalInMilliSec);

大多数时候它工作正常,但有时我很少在 _timer.Change(-1, -1); 行开始收到以下异常

对象引用未设置为对象的实例

此时“o”显示为空。请让我知道我做错了什么。谢谢

【问题讨论】:

  • 应用程序启动时是否出现问题?意味着您在调用构造函数之前创建事件。新的 _timer() 代码在哪里?
  • 是的@jdweng 我在应用程序启动时触发该代码,当它工作正常时,计时器事件中的代码会在 10 秒后继续运行。
  • ASP.NET 是用来处理 Web 请求的,而不是作为 Windows 服务运行的。 ASP.NET 基础结构会定期回收AppDomain,并会导致您尝试维护的计时器的调度中断。
  • @jdweng 我再次检查了该代码,发现包含计时器代码的函数在构造函数之后被调用。新的 _timer() 代码是“//等待的 api 调用到这里”
  • @TheodorZoulias 对不起我的错。我错误地添加了 asp.net 标签。这是一个 wpf 应用程序。

标签: c# wpf timer async-await


【解决方案1】:

我不知道您为什么在代码中使用 NullReferenceException,但我建议完全放弃 Timer 方法,并在循环中用更简单的 Task.Delay 替换它:

var apiCallCts = new CancellationTokenSource();
var apiCallTask = Task.Run(async () =>
{
    while (true)
    {
        var delayTask = Task.Delay(TimeSpan.FromSeconds(10), apiCallCts.Token);
        await SomeApiCallAsync();
        await delayTask;
    }
});

在应用关闭时:

apiCallCts.Cancel();

在 API 失败的情况下,上述解决方案具有不同的行为。不会让应用程序崩溃,而是会默默地停止调用 API。这是您必须考虑的事情。

【讨论】:

  • 那个空引用异常仍然是个谜,我已经实现了你的解决方案,它运行良好。您(在提供替代方案方面)比将问题标记为离题并投反对票的成员要好得多。再次感谢:)
猜你喜欢
  • 1970-01-01
  • 2016-02-20
  • 2011-12-10
  • 1970-01-01
  • 2017-08-21
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多