c# - 无法理解为什么我会收到 NullReferenceException

标签 c# multithreading nullreferenceexception

我有一段代码从队列中读取,处理一个项目(在它自己的线程中),然后重复直到队列为空。

public ActionResult GetOrdersAsync() {

        int count = 0;
        SyncDM sync = _common.StartSync();

        while (sync != null && sync.SyncId != 0) {

            int customerId;
            bool result = int.TryParse(sync.Payload, out customerId);
            if (result) {
                Task.Run(() => GetOrders(sync.SyncId, customerId));
            }

            count++;
            //Process the next Sync
            sync = _common.StartSync();

        }

        return Json(new JsonModel {
            Message = "Started " + count + " instances of GetOrders",
            Success = count > 0
        });

    }

StartSync() 从队列中删除一个项目,或者如果队列为空则返回 null。 GetOrders() 处理对象。

问题是有时代码会在这一行引发 NullReferenceException Task.Run(() => GetOrders(sync.SyncId, customerId));

在调试器中,Sync 为null(异常原因),但customerId 有值。这告诉我 sync 在上一行有一个值。这让我感到困惑,我认为它与 Task.Run 和线程有关,但我不明白局部范围的变量如何自发地改变它的值。

最佳答案

在您的任务有机会对其进行操作之前,您正在更新 sync 的引用。请注意,任务不一定立即开始。在某些情况下,您的任务可能会在进一步执行以下操作后开始:

sync = _common.StartSync();

现在您对 sync 的引用可能为空,当您的任务去访问 sync.SyncId 时,您会得到一个空引用异常。

将您的代码更改为以下内容:

if (result) {
    var syncId = sync.SyncId;
    Task.Run(() => GetOrders(syncId, customerId));
}

之所以可行,是因为我们只想传入 Id。如果你想传入对象本身怎么办?您需要创建一个新变量,该变量不会在闭包之外被修改:

if (result) {
    var capturedSync = sync;
    //Assuming GetOrders now takes a `Sync`
    Task.Run(() => GetOrders(capturedSync, customerId));
}

关于c# - 无法理解为什么我会收到 NullReferenceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41134437/

相关文章:

c# - 使用 Ajax 的 Asp.Net 页面每次都重新加载整个页面,为什么?

c# - 有没有办法创建接受 <= N 参数的参数化查询或存储过程?

c# - lambda 表达式含义/修饰

Java 如何在Java中为SQLITE创建查询队列以防止数据丢失?

python - 为什么需要 processEvents() 才能让 QThread 工作?

c# - 使用 Linq 进行 GroupBy 和选择

C#:在漫长的过程中显示模态进度对话框

c# - 为什么在与 null 类型之间映射时 null 不会导致 NullReferenceException?

C# 根据日期时间值和 ID 从数据库获取约会

c# - 为什么这会给出 NullReferenceException?