我用xferdata,以及异步begindataxfer / waitforxfer / finishdataxfer,多个线程之间没有任何问题,但我没有把结果在一个共享的队列。您使用的是哪种锁定机构?锁(这){ /* */ }做的东西是一种很好的方式得到死锁因为其他代码可以锁在这不同的原因。你应该创建专门用于锁定数据传输对象和锁定,只传输代码。对象datatransferlockobject =新object();锁(datatransferlockobject){ /* */ }做的东西,其实你真的应该使用队列。同步的方法得到一个队列的包装,不需要通过一个锁保护;看到HTTP:/ / MSDN。微软。COM / en-u. .. ueue.synchronized.aspx缩小你的问题,你可以试试其他的东西。让xferdata会但注释添加到队列。将它们添加到两个单独的队列中。就是说,我有我的app CyAPI函数不仅造成问题,但Visual Studio锁定直到我拔掉插头。我认为问题是通过托管字节[]数组的非托管程序。在转移过程中,CLR决定将缓存在内存中,可能是为了保持堆太分散。然而,由于柏驱动程序是非托管的,有没有办法知道,CLR是移动的东西,在它的后面,所以继续读/写旧的记忆。这会导致各种问题;应用程序可以锁定,或抛出NullReferenceException或者更奇特的executionengineexception,但是对我来说,例外总是扔在主线程和辅助线程(也许不是司机是在主线程上下文执行线程而不是调用线程?)考虑到当你的项目添加到队列中,它可能会导致新的内存被分配和老内存被释放。最终,记忆变得支离破碎,CLR将周围的缓冲区,如果CLR动作缓冲而司机积极转移到/从它,你会崩溃。该解决方案是使用一个固定的块缓冲区的范围的时间,或者使用GCHandle类销缓冲记忆如此之CLR不会移动它们。注意我所说的“缓冲区”,复数;这些规则不仅适用于数据缓冲区,但重叠单传输缓冲区以及!我结束了PinnedBuffer的课,把一个字节[],引脚在构造函数的缓冲区写入。不幸的是,字节[ ]必须是一个公共领域,因为柏API使用ref参数和参考参数有效的参数列表是比你想象的短很…
以上来自于百度翻译
以下为原文
I used XferData, as well as the asynchronous BeginDataXfer/WaitForXfer/FinishDataXfer, across multiple threads without any problems, but I was not placing the results in a shared queue.
What kind of locking mechanism are you using? lock (this) { /* do stuff */} is a good way to get deadlocks because other code can lock on this for different reasons. You should create an object specifically for locking data transfers and lock only the transfers on only that code.
Object DataTransferLockObject = new Object();
lock (DataTransferLockObject) { /* do stuff */ }
Actually you should really use the Queue.Synchronized method to get a queue wrapper that doesn't need protected by a lock; see
http://msdn.microsoft.com/en-u...ueue.synchronized.aspx
To narrow down your problem, you could try some other things. Keep both XferData's going but comment out adding them to the queue. Add them to two separate queues.
That said, I have had problems with the CyAPI causing not only my app, but Visual Studio to lock up until I pulled the plug. I believe the problem deals with passing Managed byte[] arrays to the Unmanaged driver. During the transfer, the CLR decides to move the buffer around in memory, probably in an effort to keep the heap from becoming too fragmented. However, since the Cypress driver is unmanaged, it has no way of knowing that the CLR is moving things behind its back, and so it continues to read/write to old memory. This can cause all kinds of problems; the app might lock, or throw a NullReferenceException or the even more exotic ExecutionEngineException, but for me the exceptions were always thrown on the main thread and not the worker thread (perhaps the driver thread was executing in the context of the main thread instead of the calling thread?)
Consider that when you add an item to the queue, it may cause new memory to be allocated and old memory to be freed. Eventually, memory becomes so fragmented that the CLR moves the buffers around, and if the CLR moves your buffer while the driver is actively transferring to/from it, you will get crashes.
The solution is to use a fixed block for duration of the buffers' scopes, or to use the GCHandle class to pin the buffers in memory so the CLR won't move them around. Note that I said "buffers", plural; these rules apply not only to the data buffer, but to the overlapped and single-transfer buffers as well!
I ended up writing a PinnedBuffer class that wraps a byte[] which pins the buffer in the constructor. Unfortunately, the byte[] must be a public field, because the Cypress API uses ref parameters and the list of valid arguments for ref parameters is actually much shorter than you think...
我用xferdata,以及异步begindataxfer / waitforxfer / finishdataxfer,多个线程之间没有任何问题,但我没有把结果在一个共享的队列。您使用的是哪种锁定机构?锁(这){ /* */ }做的东西是一种很好的方式得到死锁因为其他代码可以锁在这不同的原因。你应该创建专门用于锁定数据传输对象和锁定,只传输代码。对象datatransferlockobject =新object();锁(datatransferlockobject){ /* */ }做的东西,其实你真的应该使用队列。同步的方法得到一个队列的包装,不需要通过一个锁保护;看到HTTP:/ / MSDN。微软。COM / en-u. .. ueue.synchronized.aspx缩小你的问题,你可以试试其他的东西。让xferdata会但注释添加到队列。将它们添加到两个单独的队列中。就是说,我有我的app CyAPI函数不仅造成问题,但Visual Studio锁定直到我拔掉插头。我认为问题是通过托管字节[]数组的非托管程序。在转移过程中,CLR决定将缓存在内存中,可能是为了保持堆太分散。然而,由于柏驱动程序是非托管的,有没有办法知道,CLR是移动的东西,在它的后面,所以继续读/写旧的记忆。这会导致各种问题;应用程序可以锁定,或抛出NullReferenceException或者更奇特的executionengineexception,但是对我来说,例外总是扔在主线程和辅助线程(也许不是司机是在主线程上下文执行线程而不是调用线程?)考虑到当你的项目添加到队列中,它可能会导致新的内存被分配和老内存被释放。最终,记忆变得支离破碎,CLR将周围的缓冲区,如果CLR动作缓冲而司机积极转移到/从它,你会崩溃。该解决方案是使用一个固定的块缓冲区的范围的时间,或者使用GCHandle类销缓冲记忆如此之CLR不会移动它们。注意我所说的“缓冲区”,复数;这些规则不仅适用于数据缓冲区,但重叠单传输缓冲区以及!我结束了PinnedBuffer的课,把一个字节[],引脚在构造函数的缓冲区写入。不幸的是,字节[ ]必须是一个公共领域,因为柏API使用ref参数和参考参数有效的参数列表是比你想象的短很…
以上来自于百度翻译
以下为原文
I used XferData, as well as the asynchronous BeginDataXfer/WaitForXfer/FinishDataXfer, across multiple threads without any problems, but I was not placing the results in a shared queue.
What kind of locking mechanism are you using? lock (this) { /* do stuff */} is a good way to get deadlocks because other code can lock on this for different reasons. You should create an object specifically for locking data transfers and lock only the transfers on only that code.
Object DataTransferLockObject = new Object();
lock (DataTransferLockObject) { /* do stuff */ }
Actually you should really use the Queue.Synchronized method to get a queue wrapper that doesn't need protected by a lock; see
http://msdn.microsoft.com/en-u...ueue.synchronized.aspx
To narrow down your problem, you could try some other things. Keep both XferData's going but comment out adding them to the queue. Add them to two separate queues.
That said, I have had problems with the CyAPI causing not only my app, but Visual Studio to lock up until I pulled the plug. I believe the problem deals with passing Managed byte[] arrays to the Unmanaged driver. During the transfer, the CLR decides to move the buffer around in memory, probably in an effort to keep the heap from becoming too fragmented. However, since the Cypress driver is unmanaged, it has no way of knowing that the CLR is moving things behind its back, and so it continues to read/write to old memory. This can cause all kinds of problems; the app might lock, or throw a NullReferenceException or the even more exotic ExecutionEngineException, but for me the exceptions were always thrown on the main thread and not the worker thread (perhaps the driver thread was executing in the context of the main thread instead of the calling thread?)
Consider that when you add an item to the queue, it may cause new memory to be allocated and old memory to be freed. Eventually, memory becomes so fragmented that the CLR moves the buffers around, and if the CLR moves your buffer while the driver is actively transferring to/from it, you will get crashes.
The solution is to use a fixed block for duration of the buffers' scopes, or to use the GCHandle class to pin the buffers in memory so the CLR won't move them around. Note that I said "buffers", plural; these rules apply not only to the data buffer, but to the overlapped and single-transfer buffers as well!
I ended up writing a PinnedBuffer class that wraps a byte[] which pins the buffer in the constructor. Unfortunately, the byte[] must be a public field, because the Cypress API uses ref parameters and the list of valid arguments for ref parameters is actually much shorter than you think...
举报