我的C#应用程序正在使用后台工作程序等待某些传输数据的确认。这是一些伪造的代码,展示了我正在尝试做的事情:
UI_thread
{
TransmitData()
{
// load data for tx
// fire off TX background worker
}
RxSerialData()
{
// if received data is ack, set ack received flag
}
}
TX_thread
{
// transmit data
// set ack wait timeout
// fire off ACK background worker
// wait for ACK background worker to complete
// evaluate status of ACK background worker as completed, failed, etc.
}
ACK_thread
{
// wait for ack received flag to be set
}
ACK BackgroundWorker会超时,并且永远不会收到确认。我很确定它是由远程设备传输的,因为该设备根本没有改变,而且C#应用程序正在传输。我已经改变了ack线程(当它工作时)......
for( i = 0; (i < waitTimeoutVar) && (!bAckRxd); i++ )
{
System.Threading.Thread.Sleep(1);
}
......对此...
DateTime dtThen = DateTime.Now();
DateTime dtNow;
TimeSpan stTime;
do
{
dtNow = DateTime.Now();
stTime = dtNow - dtThen;
}
while ( (stTime.TotalMilliseconds < waitTimeoutVar) && (!bAckRxd) );
与前者相比,后者产生非常精确的等待时间。但是,我想知道删除睡眠功能是否会干扰接收串行数据的能力。 C#是否只允许一次运行一个线程,也就是说,我是否必须在一段时间内让线程进入休眠状态以允许其他线程运行?
您可能会有任何想法或建议,我们将不胜感激。我使用的是Microsoft Visual C#2008 Express Edition。感谢。
答案 0 :(得分:3)
为了回答C#是否允许一次运行一个线程的直接问题,C#与线程没有任何关系。但是,.NET框架允许您一次运行多个(逻辑)线程。如何实际处理是框架和操作系统的功能。
至于你的问题,我认为你有太多的线程处于等待状态开始。您发送和接收数据的方法应该具有异步调用模型(开始和结束)。因此,您应该通过调用Begin开始传输,然后附加在函数终止时调用的回调。
然后,在回调中,您将处理结果并继续执行下一个异步操作(如有必要)或更新UI。
答案 1 :(得分:3)
你的“新”版本的RX线程正在利用100%的处理器时间 - 它只是连续运行而且从不睡觉。除了这种方法的一般邪恶性质,这个可能(虽然不一定)阻止其他一些事情,如接收数据,按时发生。
对于这样的等待场景,通常会使用名为 event 的线程同步构造。您创建一个“事件”对象,并且RX线程等待它,而处理线程在收到ACK时发出信号。
AutoResetEvent event = new AutoResetEvent( false );
// ...
// ACK waiting thread:
event.WaitOne();
// ...
// ...
// Whatever thread actually receives the ACK
if ( /* ack received */ )
{
// bAckRxd = true; - comment this out. Replace with following:
event.Set();
}
至于为什么你没有收到你的ACK,我需要更多的信息。通道究竟是什么?它是串口吗?网络?管?还有别的吗?
答案 2 :(得分:1)
您的代码非常高兴。当你期望他们计时时,这确实会让你陷入困境。特别是当您使用BGW或线程池线程时,调度程序仅允许它们在没有比CPU内核更多的线程活动时运行。或者当线程被“卡住”一段时间。你的卡住了。您似乎也没有有效地使用它们,轮询循环会消耗大量不必要的CPU周期。
利用SerialPort类的功能来避免这种情况:
Sleep()不会干扰串口,它们的驱动程序使用硬件中断读取数据。