C# 在主线程C的睡眠模式期间处理从事件处理程序发送的数据#
假设我在C#中有一个事件侦听器,它等待来自串行端口的数据,这些数据在通过设置某些状态捕获后返回。在主循环中,我查看该状态,并根据该状态决定下一步要做什么 为此,我首先将命令写入串行端口,并使用Thread.Sleep方法等待输出。当主线程仍处于睡眠模式时,事件侦听器将已经发送数据,并且没有任何操作来处理该场景 有谁能告诉我这种情况下会有什么后果以及如何预防 代码是这样的C# 在主线程C的睡眠模式期间处理从事件处理程序发送的数据#,c#,multithreading,serial-port,C#,Multithreading,Serial Port,假设我在C#中有一个事件侦听器,它等待来自串行端口的数据,这些数据在通过设置某些状态捕获后返回。在主循环中,我查看该状态,并根据该状态决定下一步要做什么 为此,我首先将命令写入串行端口,并使用Thread.Sleep方法等待输出。当主线程仍处于睡眠模式时,事件侦听器将已经发送数据,并且没有任何操作来处理该场景 有谁能告诉我这种情况下会有什么后果以及如何预防 代码是这样的 bool status = false; //main thread private void Main() {
bool status = false;
//main thread
private void Main()
{
//some Code
serialPort.Write("something");
//Wait for 10 sec
Thread.Sleep(10000);
while(status == false)
{
// do something else
}
}
//Ignore the syntax, this is just to make people understand
public void OndataReceived(object sender, EventArg arg)
{
//Function that recieve the data
Receive();
//change status to true
status = true;
return;
}
这个问题措辞笨拙,但如果我理解正确的话,您是在问,如果数据接收时间早于10秒,如何避免等待10秒 可以使用较旧的同步对象,例如
WaitHandle
子类之一、Monitor
,甚至是信号量。但是对于这种类型的场景,当前的C#习惯用法是使用TaskCompletionSource
,它提供了一个可等待的对象和同时返回结果值的选项
例如:
TaskCompletionSource<bool> _result;
//main thread
private void Main()
{
//some Code
serialPort.Write("something");
_result = new TaskCompletionSource<bool>();
// Normally, one should "await" a Task. But in the Main() method, which
// cannot be "async", we have to just wait synchronously.
Task completed = Task.WhenAny(_result.Task,
Task.Delay(TimeSpan.FromSeconds(10)).Result;
// Don't check "_result.Result" unless the task has completed,
// because otherwise the thread will block. If it is completed,
// check "_result.Result" as the equivalent to examining the "status"
// variable in the previous code example.
while(!_result.IsCompleted || !_result.Result)
{
// do something else
}
}
public void OndataReceived(object sender, EventArg arg)
{
//Function that recieve the data
Receive();
//change status to true
_result.SetResult(true);
return;
}
TaskCompletionSource\u结果;
//主线
私有void Main()
{
//一些代码
serialPort.Write(“某物”);
_结果=新任务完成源();
//通常,应该“等待”任务
//不能“异步”,我们只能同步等待。
Task completed=Task.Wheny(_result.Task,
任务延迟(时间跨度从秒(10))。结果;
//除非任务已完成,否则不要选中“\u result.result”,
//因为否则线程会阻塞。如果它完成,
//检查“_result.result”等同于检查“status”
//前面代码示例中的变量。
而(!_result.IsCompleted | |!_result.result)
{
//做点别的
}
}
公共无效OndataReceived(对象发送方,事件参数)
{
//接收数据的函数
接收();
//将状态更改为true
_result.SetResult(true);
返回;
}
这个问题措辞笨拙,但如果我理解正确,您会问,如果数据接收时间早于10秒,如何避免等待10秒
可以使用较旧的同步对象,例如WaitHandle
子类之一、Monitor
,甚至是信号量。但对于这种类型的场景,当前的C习惯用法是使用TaskCompletionSource
,它同时提供可等待对象和返回结果值的选项。
例如:
TaskCompletionSource<bool> _result;
//main thread
private void Main()
{
//some Code
serialPort.Write("something");
_result = new TaskCompletionSource<bool>();
// Normally, one should "await" a Task. But in the Main() method, which
// cannot be "async", we have to just wait synchronously.
Task completed = Task.WhenAny(_result.Task,
Task.Delay(TimeSpan.FromSeconds(10)).Result;
// Don't check "_result.Result" unless the task has completed,
// because otherwise the thread will block. If it is completed,
// check "_result.Result" as the equivalent to examining the "status"
// variable in the previous code example.
while(!_result.IsCompleted || !_result.Result)
{
// do something else
}
}
public void OndataReceived(object sender, EventArg arg)
{
//Function that recieve the data
Receive();
//change status to true
_result.SetResult(true);
return;
}
TaskCompletionSource\u结果;
//主线
私有void Main()
{
//一些代码
serialPort.Write(“某物”);
_结果=新任务完成源();
//通常,应该“等待”任务
//不能“异步”,我们只能同步等待。
Task completed=Task.Wheny(_result.Task,
任务延迟(时间跨度从秒(10))。结果;
//除非任务已完成,否则不要选中“\u result.result”,
//因为否则线程会阻塞。如果它完成,
//检查“_result.result”等同于检查“status”
//前面代码示例中的变量。
而(!_result.IsCompleted | |!_result.result)
{
//做点别的
}
}
公共无效OndataReceived(对象发送方,事件参数)
{
//接收数据的函数
接收();
//将状态更改为true
_result.SetResult(true);
返回;
}
您真正需要的是独立的线程、状态机和委托(回调)。我在这里写了一个不错的示例:您真正需要的是独立的线程、状态机和委托(回调)。我在这里写了一个不错的例子:看看手动和自动reseteventcreate自定义事件,从OndataReceived
方法内部启动它,然后在我看来的方法中执行下一步:看看手动和自动reseteventcreate自定义事件,从OndataReceived
方法内部启动它,然后执行以下操作:我的观点中方法的下一步是Tanks Peter。是的,我想说同样的话。但是在我的例子中,如果数据是在主线程发送时发送的,这是通过执行thread.Start(main)启动的,处于睡眠模式,整个windows服务都会挂起,因此您的回答可能会对我有所帮助。还有一件事,我有很多地方使用线程。使用睡眠时,使用新任务对象是否安全?“我有很多地方使用线程。使用睡眠时,使用新任务对象是否安全?”--无论在哪里,只要有Thread.Sleep()
,您都应该寻找替代实现(如上面所述)。Thread.Sleep()
方法从来都不是延迟处理的好方法,因为它阻塞了调用它的线程,而现代C#有更好的/有用的方法来实现相同的结果。谢谢Peter。是的,我想说同样的话。但是在我的情况下,如果数据是在主线程发送时发送的,则通过执行thread.Start(main)启动主线程,处于睡眠模式,整个windows服务都会挂起,因此您的回答可能会对我有所帮助。还有一件事,我有很多地方使用线程。使用睡眠时,使用新任务对象是否安全?“我有很多地方使用线程。使用睡眠时,使用新任务对象是否安全?”--无论您在哪里使用Thread.Sleep()
,您都应该寻找替代实现(如上面所述)。Thread.Sleep()
方法从来都不是延迟处理的好方法,因为它会阻塞调用它的线程,而现代C#有更好/有用的方法来实现相同的结果。