我有一个类,它使用C#中的DataReceived事件处理程序从串口读取.当我收到数据时,我知道标题将有5个字节,所以我不想对数据做任何事情,直到我至少有.我目前的代码如下:
while (serialPort.BytesToRead<5)
{
//Do nothing while we have less bytes than the header size
}
//Once at least 5 bytes are received, process header
Run Code Online (Sandbox Code Playgroud)
据我了解,这段代码是阻塞的,需要改进.我正在寻找有关如何做到这一点的建议.DataReceived事件处理程序中的另一个事件处理程序是否合适?
我正在查看http://www.albahari.com/threading/part4.aspx中描述的有关内存屏障的部分, 并试图制作"我们真的需要锁定和"下提供的示例的异步/等待版本壁垒"?
public class Program
{
static void Main(string[] args)
{
TestAsync();
Console.ReadKey(true);
}
private static async void TestAsync()
{
bool complete = false;
Func<Task> testFunc = async () =>
{
await Task.Delay(1000);
bool toggle = false;
while (!complete) toggle = !toggle;
};
var task = testFunc();
Thread.Sleep(2000);
complete = true;
await task;
Console.WriteLine("Done");
}
}
Run Code Online (Sandbox Code Playgroud)
在没有调试的情况下在释放模式下运行时,程序将永远不会按照它所基于的原始线程示例完成.
但是,由于上下文保存的方式,我在async/await的印象下会阻止这些问题.或者在使用async/await时是否仍然适用所有线程安全规则?
我编写了以下函数来使用NetworkStream异步读取函数(BeginRead和EndRead)实现超时功能.它工作正常,直到我注释掉该行Trace.WriteLine("bytesRead: " + bytesRead);.为什么?
private int SynchronousRead(byte[] buffer, int count)
{
int bytesRead = 0;
bool success = false;
IAsyncResult result = null;
result = _stream.BeginRead(
buffer, 0, count,
delegate(IAsyncResult r)
{
bytesRead = _stream.EndRead(r);
},
null);
success = result.AsyncWaitHandle.WaitOne(_ioTmeoutInMilliseconds, false);
if (!success)
{
throw new TimeoutException("Could not read in the specfied timeout.");
}
//If I remove this line, bytesRead is always 0
Trace.WriteLine("bytesRead: " + bytesRead);
return bytesRead;
}
Run Code Online (Sandbox Code Playgroud)
万一你想知道,我必须这样做,因为我最终需要针对.Net Compact …
我使用NetworkStream带TcpClient。
首先我设置我的 tcp 客户端:
tcp = new TcpClient(AddressFamily.InterNetwork)
{ NoDelay = true, ReceiveTimeout = 5000};
Run Code Online (Sandbox Code Playgroud)我的主要数据接收循环:
while (true)
{
//read available data from the device
int numBytesRead = await ReadAsync();
Console.WriteLine($"{numBytesRead} bytes read"); //BP2
}
Run Code Online (Sandbox Code Playgroud)和实际的 TCP 数据读取:
public Task<int> ReadAsync()
{
var stream = tcp.GetStream();
return stream.ReadAsync(InBuffer, 0, InBuffer.Length); //BP1
}
Run Code Online (Sandbox Code Playgroud)我将它连接到一个测试平台,让我可以发送手动数据包。通过设置断点和调试,我检查了stream.ReadTimeout从tcp.
如果我经常发送数据,它会按预期工作。但是如果我不发送任何数据,5 秒后似乎什么也没有发生,没有超时。我看到BP1在调试器中断点被击中,但直到我从我的测试平台发送数据,才被BP2击中。我可以离开它一分钟或更长时间,它似乎只是在等待,但在一分钟后接收发送的数据,这似乎是不正确的行为。5 秒后肯定会发生一些事情(据我所知是一个例外)?
太晚了,所以我期待一些非常基本的东西,但谁能看到我的错误和解决方案?
好的,所以当我对我正在使用的实际 .Net 版本进行 RTFM 时(我有多少次被默认为 .Net …