问题
Do we have in .NET 4.0 the opportunity to wait for a response and then to return the response?
Currently I'm doing it like this but it isn't really nice and I don't like it:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
byte[] options = new byte[]{1,1,0};
COMManager mgr = new COMManager("COM1");
byte[] result = mgr.GetResponse(options);
}
}
And my COM Manager Class (I have to do the operation in a seperate class (dll)):
public class COMManager
{
SerialPort sp = null;
byte[] result = null;
bool completed = false;
public COMManager(string comport)
{
sp = new SerialPort(comport);
sp.DataReceived +=new SerialDataReceivedEventHandler(sp_DataReceived);
}
public byte[] GetResponse(byte[] option)
{
sp.Write(option, 0, option.Length);
//I don't like the way...
while (!completed) { }
completed = false;
return result;
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
result = new byte[sp.BytesToRead];
sp.Read(result, 0, sp.BytesToRead);
completed = true;
}
}
In .NET 4.5 we may have the opportunity to use the "await" statement. But for the current project we only are allowed to use .NET 4.0. Any ideas?
回答1:
For your original question, to block the executing thread you can use a ManualResetEvent or AutoResetEvent which will get Set
when your response has been obtained. There's a fairly good explanation on the page.
For threading, the rule of thumb is that if you're not extremely clear on what you're doing, don't do it.
Synchronous blocking when you have access to events seems like a waste. Considering that the data is a stream, this might end up being a hard to maintain abstraction.
There's a longer explanation of the above idea with an example over here.
You can also do this in async with TaskCompletionSource
. Instead of set, you can call SetResult
, and you await the .Task
, but the idea is pretty much the same.
回答2:
There's no point in using the DataReceived event if you don't want to read asynchronously. Simply call the Read() method directly in GetResponse().
Beware that you cannot assume you will get a complete response, you cannot ignore the return value of Read(). It usually returns a couple of bytes only, serial ports are pretty slow. So be sure to keep calling Read() until you got the entire response.
回答3:
The clean way would be to wait on an AutoResetEvent
and for for the receive callback to signal it.
By creating a wrapper with this method, you can effectivly await
in every version of .Net.
来源:https://stackoverflow.com/questions/11782053/serialport-wait-for-response