如何在C#中取消引用对象?

时间:2014-11-21 20:31:07

标签: c# pointers object reference

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

    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方法,因为在任务运行时obj不再存在。我希望能够保留旧对象,直到它被写出并让缓冲区指向一个新对象。

我想做什么:

    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()

根据要求,“真实代码”

    CancellationTokenSource cts = new CancellationTokenSource();
    public void StartMachine()
    {
        Task.Factory.StartNew(() =>
            {
                _isFirstData = true;
                _expiredFlag = false;
                Plc.StartPLC();
                Plc.Start();

                while (true)
                {
                    if (!_paused && !Plc.IsInputStackEmpty() && !Plc.IsOutputSlideOpen())
                    {

                        CameraFront.SnapAquire();

                        // If this is the first data set the wait handles
                        if (!_isFirstData)
                        {
                            CameraBack.SnapAquire();
                        }
                        else
                        {
                            _imageBackRecieved.Set();
                            _databaseInfoRecieved.Set();
                            //_isFirstCard = false;
                        }

                        // Wait for 3 things! Image Front, Image Back, Database
                        bool gotEvents = WaitHandle.WaitAll(_waitHandles, TIMEOUT);
                        if (gotEvents)
                        {
                            if (!_isFirstData)
                            {
                                if (Buffer[1 - NextDataOutIndex].IsDataComplete())
                                {
                                    if (Buffer[1 - NextDataOutIndex].EvaluateData()) 
                                    {
                                        OnPassFailNotification()
                                        Plc.Pass();
                                    }
                                    else
                                    {
                                        OnPassFailNotification()
                                        Plc.Fail();
                                    }
                                }
                                else
                                {
                                    OnPassFailNotification()
                                    Plc.Fail();
                                    Common.Logging
                                }
                            }
                            else
                            {
                                _isFirstData = false;
                            }
                        }
                        else
                        {
                           Common.Logging("WARNING: Wait handle timed out"
                            Plc.Fail();
                        }

                        Data temp = Buffer[1 - NextDataOutIndex];
                        Task.Factory.Startnew(()=>{
                            Data.WriteData(temp);
                        }
                        Buffer[1 - NextDataOutIndex] = new Data(); 

                        // Swap card buffers - alternate between 1 and 0
                        NextdataOutIndex = 1 - NextDataOutIndex;

                        // Do this
                        Plc.WheelAdvance();
                    }
                    else
                    {
                    }
                }
            }, cts.Token);                
    }


    public static void WriteData(Data data)
    {
        if(WRITE_BATCH_FILES)
        try
        {
            if (data.ImageFront != null)
            {
                string filenameforfront = "blahlbah-front.tiff";
                OperatorSet.WriteImage(data.ImageFront, "tiff", 0, filenameforfront);
            }
            if (data.ImageBack != null)
            {
                string filenameforback = "blahblah-back.tiff";
                HOperatorSet.WriteImage(data.ImageBack, "tiff", 0, filenameforback);
            }
        }
        catch (Exception ex)
        {
            Common.Logging.
            //throw ex;
        }

        //TODO: Write out data in xml
        //TODO: Write out metrics
    }

2 个答案:

答案 0 :(得分:2)

在你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);
    };

}

答案 1 :(得分:0)

听起来像Semaphores的工作! 信号量是线程间通信的一种形式,对于这种情况是理想的,因为它们允许一个线程锁定信号量而另一个线程再次释放信号量。在下面的代码示例中,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
}