【发布时间】:2014-11-21 20:31:06
【问题描述】:
我有一个在两个索引之间循环的缓冲区,我想在任务中写出当前索引处的对象,并允许程序的其余部分继续处理事情。我试图在保留所有相关部分的同时简化流程。
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
}
【问题讨论】:
-
“问题在于,通过将缓冲区项分配给一个新对象,我正在杀死 writeOutObject 方法,因为在任务运行时 obj 不再存在” - 不,这不应该发生.我强烈怀疑你误诊了这个问题。一个简短但完整的程序来演示这个问题真的很有帮助。
-
顺便说一句;我在那里没有看到任何指针。
-
你们每个人都在用这些对象做某事吗?如果没有,如果您所做的只是将它们写入文件,为什么要这样缓冲它们呢?
-
@JonSkeet 不幸的是,该程序有点过于复杂,无法在此处转录。这些字段实际上是从多个事件处理程序以任意顺序填充的,并且同时填充 0 和 1 索引对象。只有当对象被完全填满时,它才会被写出。澄清一下,并不是该对象不存在,它通常只是随着缓冲区继续循环而被新数据覆盖。将尝试用更清晰的图片更新代码。
-
我没有要求您提供实际代码 - 我要求提供一个简短但完整的程序来证明问题。您可以从当前代码的副本开始,然后从中删除一些部分,直到剩下的只是一个最小的示例。您很可能会发现,在这样做的过程中,您发现了问题。
标签: c# pointers object reference