如何在C#中反引用对象?

如何在C#中反引用对象?,c#,pointers,object,reference,C#,Pointers,Object,Reference,我有一个在两个索引之间循环的缓冲区,我想在任务的当前索引处写出对象,并允许程序的其余部分继续处理。我试图在维护所有相关部分的同时简化流程 object[] buffer = new object[2] int currentIndex = 0 while(true){ buffer[currentIndex].field1 = newdatahere //data grabbed by sensor bundle buffer[curre

我有一个在两个索引之间循环的缓冲区,我想在任务的当前索引处写出对象,并允许程序的其余部分继续处理。我试图在维护所有相关部分的同时简化流程

    object[] buffer = new object[2]
    int currentIndex = 0

    while(true){
        buffer[currentIndex].field1 = newdatahere //data grabbed by sensor bundle
        buffer[currentIndex].field2 = newdatahere //data grabbed by camera bundle
        buffer[currentIndex].field3 = newdatahere //data grabbed from system snapshot

        task.factory.starnew(()=>{
            writeOutObject(buffer[currentIndex])
        }

        buffer[currentIndex] = new object();

        currentIndex = 1 - currentIndex //cycle between the 0 and 1 indices
    }

    void writeOutObject(Object obj){
        //do file IO here
        //write out field1, field2, field3
    }

问题是,通过将缓冲区项分配给一个新对象,我正在终止writeOutObject方法,因为任务运行时该对象已不存在。我希望能够保留旧对象,直到它被写出来,并有一个新对象的缓冲点

我想做的是:

    object obj1 = new object();
    obj1.field1 = data1;
    obj1.field2 = data2;
    obj1.field3 = data3;

    obj2 = obj1;
    //de-reference obj1 from the object that it was pointed to and associate it to a new object

    // i want this to write out data1,data2,data3 but instead it is 
    // writing out data4,data5,data6 or some mixture because it has 
    // been overwritten halfway through the file IO
    task.factory.startnew(()=>{ write out obj2 } 

    obj1.field1 = data4;
    obj1.field2 = data5;
    obj1.field3 = data6;
可能是这样的:

    obj1 = new object()

    obj2* = &obj1
    obj1* = &new object
一旦分配了obj1,我需要将其参考断开回obj2。简单地这样做是行不通的:

    obj1 = new object()
    obj2 = obj1
    obj1 = null // or new object()
按要求,“真正的代码”


听起来像是信号灯的工作! 信号量是线程间通信的一种形式,非常适合这种情况,因为它们允许一个线程锁定信号量,而另一个线程再次释放信号量。在下面的代码示例中,
sem.WaitOne()
行将等待调用
sem.Release()
方法。这会阻塞主线程足够长的时间,使任务能够获得所需的数据

object[] buffer = new object[2]
int currentIndex = 0

while(true){
    buffer(currentIndex).field1 = newdatahere //data grabbed by sensor bundle
    buffer(currentIndex).field2 = newdatahere //data grabbed by camera bundle
    buffer(currentIndex).field3 = newdatahere //data grabbed from system snapshot

    Semaphore sem = new Semaphore(1,1);  //Initialise the semaphore so that it is checked out

    task.factory.starnew(()=>{
        object item = buffer[currentIndex]; //Create local reference to the data item
        sem.Release(); //Check-in the semaphore (let the WaitOne method return)
        writeOutObject(item)
    }

    sem.WaitOne(); //Block until the semaphore has returned

    buffer[currentIndex] = new object();

    currentIndex = 1 - currentIndex //cycle between the 0 and 1 indices
}

void writeOutObject(Object obj){
    //do file IO here
    //write out field1, field2, field3
}

在task.factory.StartNew之前,请执行以下操作

while(...)
{
   ... bunch of other code
   buildTask(buffer[currentIndex]);
   buffer[currentIndex] = new object();
   ... bunch of other code
}

// Within this method, all references to detachedBuffer object will remain pointing to the same
// memory location no matter whether the variable passed in is reassigned.
public void buildTask(object detachedBuffer)
{
    task.factory.starnew(()=>{
        writeOutObject(detachedBuffer);
    };

}

“问题是,通过将缓冲区项分配给新对象,我正在终止writeOutObject方法,因为任务运行时该对象已不存在”-不,这不应该发生。我强烈怀疑你把问题误诊了。一个简短但完整的程序来演示这个问题真的很有帮助;我看不到任何指示。你真的对这些对象做了一些事情吗?如果不是的话,如果你所做的只是将它们写入一个文件,为什么还要像那样缓冲它们呢?@JonSkeet不幸的是,这个程序太复杂了,无法在这里转录。实际上,这些字段是按照多个事件处理程序的任意顺序填充的,并且同时填充0和1索引对象。只有当对象完全填写时,它才会被写出来。要澄清的是,并不是对象不存在,它通常只是在缓冲区继续循环时被新数据覆盖。我将尝试用更清晰的图片更新代码。我没有要求你的实际代码-我要求一个简短但完整的程序来演示这个问题。您可以从当前代码的一个副本开始,并从中删除一些内容,直到只剩下一个最小的示例。你很可能会发现,在这样做的过程中,你发现了问题所在。你认为为什么需要这样做?我看不出有任何理由跳出去锁定。我相信OP已经误诊了这个问题,但我看不出你的建议会有什么帮助。这恰恰否定了使用异步块的意义。它可以工作,但OP也可以在线调用writeOutObject。@Jonsket-我读它的方式,除非writeOutObject(buffer[currentIndex])在buffer[currentIndex]=new object()之前执行;(这不是保证,因为这是一项任务)那么OP在写入磁盘之前确实会看到他的缓冲区[currentIndex]被设置为新对象。@PhillipH:但是如果
writeOutObject
使用它所传递的参数,
buffer
与它完全无关。
buffer
中的元素不再具有相同的值并不重要,
writeOutObject
方法已经有了它试图写入的对象的引用。OP声称该对象被“杀死”的说法与他们发布的代码毫无意义。OP似乎有种族条件。他们启动了一个新线程(TaskFactory.StartNew),该线程需要一组数据,但随后会立即更改数据。在线程池上执行
writeOutObject(buffer[currentIndex])
时,
buffer[currentIndex]=new object()可能已经被执行了。这绝对比我的建议好-在嵌入式C中工作太多时间会对人的大脑造成不良影响!不幸的是,这种方法也有同样的问题。只要缓冲区[currentIndex]=新对象();执行时,它仍然指向与detachedBuffer相同的数据。如果detachedBuffer在任务启动前重新初始化,则会发生这种情况;这在这样一个小循环中是可能的。要使此操作一直有效,您应该将任务初始化放在其自己的方法中,并将detachedBuffer对象作为参数传递给该方法。这将确保任务委托中的detachedBuffer语义始终与执行该方法时传递给该方法的语义相同。我已经相应地修改了我的答案。我相信这已经解决了问题。方法调用会一直阻塞,直到任务使用它自己对分离的缓冲区的引用完全启动,然后方法返回,循环的其余部分可以继续执行。如果我看到任何其他异常,将更新。
while(...)
{
   ... bunch of other code
   buildTask(buffer[currentIndex]);
   buffer[currentIndex] = new object();
   ... bunch of other code
}

// Within this method, all references to detachedBuffer object will remain pointing to the same
// memory location no matter whether the variable passed in is reassigned.
public void buildTask(object detachedBuffer)
{
    task.factory.starnew(()=>{
        writeOutObject(detachedBuffer);
    };

}