Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.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
c#等待任务-局部变量意外更改_C#_Asp.net_Asynchronous_Asp.net Web Api - Fatal编程技术网

c#等待任务-局部变量意外更改

c#等待任务-局部变量意外更改,c#,asp.net,asynchronous,asp.net-web-api,C#,Asp.net,Asynchronous,Asp.net Web Api,我刚刚开始在我正在编写的一些方法中实现异步编程 业务逻辑是接受入站调用,处理一个项目(如果它不在全局缓存中),或者如果它在全局缓存中,只需更新条目,然后在代码中稍后处理该条目 然而,我看到一些奇怪的行为,我不能左右我的头。我的单元测试向我的QueueProcessor方法提交两个请求(每次调用之间有2秒的延迟)。为了进行测试,我特意在QueueProcessor处理请求时调用的另一个方法中使用了task.delay。这模拟了一个真实的测试用例,在第一个请求被处理时,我们会保留额外的请求 我在名为

我刚刚开始在我正在编写的一些方法中实现异步编程

业务逻辑是接受入站调用,处理一个项目(如果它不在全局缓存中),或者如果它在全局缓存中,只需更新条目,然后在代码中稍后处理该条目

然而,我看到一些奇怪的行为,我不能左右我的头。我的单元测试向我的QueueProcessor方法提交两个请求(每次调用之间有2秒的延迟)。为了进行测试,我特意在QueueProcessor处理请求时调用的另一个方法中使用了task.delay。这模拟了一个真实的测试用例,在第一个请求被处理时,我们会保留额外的请求


我在名为ProcessRoutine的子方法的作用域中使用了一个局部变量。但由于某种原因,当第二个调用用于更新全局缓存时,仅在ProcessRoutine方法范围内的局部变量也会发生更改

此外,第二个请求将只更新全局缓存变量然后停止的操作逻辑。因此,不会触发其他代码。我已经通过日志证实了这一点。我就是不明白为什么ProessRoutine方法中传递的数据集可以这样更改

public async Task<bool> QueueProcessor(RtcPluginModel_IncidentModel passInModel)
    {


        //Ensure the processing cache is instantiated
        if (QueueGlobalVariables.processingCache == null)
        {
            QueueGlobalVariables.processingCache = new List<tempTicketData>();
        }

        try
        {



            tempTicketData ticketItem = (tempTicketData)passInModel;

            ticketItem.timeStamp = DateTime.Now;

            var checkItemExistsInProcessingCache =
                QueueGlobalVariables.processingCache.Find(
                    x => x.PAName == passInModel.PAName);


            if (checkItemExistsInProcessingCache != null)
            {

                var result = QueueGlobalVariables.processingCache.Remove( QueueGlobalVariables.processingCache.Find(
                    x => x.PAName == passInModel.PAName && x.recordId == passInModel.recordId));

                QueueGlobalVariables.processingCache.Add(ticketItem);

                logger.Trace("Stopping update branch of code as no further action needed at this point.");
            }
            else
            {

                QueueGlobalVariables.processingCache.Add(ticketItem);

                do
                {

                    var cycleTickets = QueueGlobalVariables.processingCache.Find(
                        x => x.PAName == passInModel.PAName);


                    var task = Task.Run(() => ProcessRoutineAsync(cycleTickets));

                    await task;

                } while (QueueGlobalVariables.processingCache.Find(
                    x => x.PAName == passInModel.PAName) != null);

            }
        }
        catch (Exception e)
        {
            logger.Trace("An exception has occured in the queue handler class: " + e.Message);

        }

        return true;
    } 
****更新

我已经找到了一个解决问题的方法,但我仍然不明白为什么会发生这种情况:o/

我修改了QueueProcessor,使另一个变量独占地保存时间戳:

   var ticketInstance = passInModel;
   var saveTimeIndex = ticketInstance.timeStamp;

然后,我将新变量传递给if语句,该语句将刚刚处理的票证的时间戳与缓存中的内容进行比较。现在一切正常。但是首先肯定不需要这个新变量吗?

EnterticketData
是一个类。在C#中,所有
class
e都是引用类型。所有指向类实例的引用都指向数据的一个副本。当您更改此通用副本时,每个人都会看到更改(最终,多线程是很难的)

当您执行
(诱惑icketdata)passInModel
时,不会复制票据,它仍然是对同一票据的引用。因此,当您稍后修改它时,您将修改缓存中的票证,而不仅仅是本地票证-本地票证只是对缓存中对象的引用,而不是对象的副本

这是一件大事。确保您完全理解这是如何工作的——这是编程的基础之一,也是理解编程的主要障碍之一

一般来说,这是一个间接的问题。让我们想象一个简单的虚拟机,它代表您的(简化的)程序

您有一个
enticketdata
对象,一张纸,存储在冰箱中的C42框中。在这张纸上,你写了
Hi。您的缓存对象有一个便利贴,上面写着“我的对象存储在冰箱中,在C42框中”。现在,当你从缓存中读取票证时,你所读的只是便笺——因为C#的工作方式,它还允许你访问真实实例的所有成员。因此,当你使用诸如
Console.WriteLine(ticket.timeStamp)
之类的代码时,C#会看一下邮件,走到冰箱前,给你读报纸


现在,当你制作你的本地,
ticketItem
,你复制了post-it,它还写着“我的物品储存在冰箱里,在C42框中”。当您更改
ticketItem.timeStamp
时,您将进入冰箱,进入C42框,并更换纸张。毫不奇怪,当有人读到原始的post-it并走到冰箱前时,他也会看到你的更改-只有一个
EnterticketData
对象。多张便笺指向冰箱中的同一位置这一事实没有帮助——只有一张票据。

enticketdata
是一个类别。在C#中,所有
class
e都是引用类型。所有指向类实例的引用都指向数据的一个副本。当您更改此通用副本时,每个人都会看到更改(最终,多线程是很难的)

当您执行
(诱惑icketdata)passInModel
时,不会复制票据,它仍然是对同一票据的引用。因此,当您稍后修改它时,您将修改缓存中的票证,而不仅仅是本地票证-本地票证只是对缓存中对象的引用,而不是对象的副本

这是一件大事。确保您完全理解这是如何工作的——这是编程的基础之一,也是理解编程的主要障碍之一

一般来说,这是一个间接的问题。让我们想象一个简单的虚拟机,它代表您的(简化的)程序

您有一个
enticketdata
对象,一张纸,存储在冰箱中的C42框中。在这张纸上,你写了
Hi。您的缓存对象有一个便利贴,上面写着“我的对象存储在冰箱中,在C42框中”。现在,当你从缓存中读取票证时,你所读的只是便笺——因为C#的工作方式,它还允许你访问真实实例的所有成员。因此,当你使用诸如
Console.WriteLine(ticket.timeStamp)
之类的代码时,C#会看一下邮件,走到冰箱前,给你读报纸

现在,当你制作你的本地,
ticketItem
,你复制了post-it,它还写着“我的物品储存在冰箱里,在C42框中”。当您更改
ticketItem.timeStamp
时,您将进入冰箱,进入C42框,并更换纸张。毫不奇怪,当有人读到原始的post-it并走到冰箱前时,他也会看到你的更改-只有一个
EnterticketData
对象。多张便笺指向冰箱中的同一位置这一事实没有帮助,因为只有一张便笺。

是否使用相同的参数连续调用QueueProcessor()方法两次?在
[XmlInclude(typeof(tempTicketData))]
public class MyTicketModel
{
    public string recordId { get; set; }
    public string PAName { get; set; }
    public string ItemA { get; set; }
    public string ItbmB { get; set; }
}


[XmlInclude(typeof(tempTicketData))]
public class tempTicketData : MyTicketModel
{
    public DateTime timeStamp { get; set; }
}
   var ticketInstance = passInModel;
   var saveTimeIndex = ticketInstance.timeStamp;