C# 等待事件-比轮询更好的解决方案?
我正在处理一个现有项目的问题。我们想要读取一个ADC值,通常我们在那里使用一个fire-and-forget概念。我们请求该值,读取该值后引发一个事件。但是现在我必须实现一个函数,它直接返回一个值。我的想法是通过投票来解决这个问题C# 等待事件-比轮询更好的解决方案?,c#,events,wait,C#,Events,Wait,我正在处理一个现有项目的问题。我们想要读取一个ADC值,通常我们在那里使用一个fire-and-forget概念。我们请求该值,读取该值后引发一个事件。但是现在我必须实现一个函数,它直接返回一个值。我的想法是通过投票来解决这个问题 public class Information { public delegate void NewADCValueArrived(double newValue); private event NewADCValueArrived newAdcV
public class Information
{
public delegate void NewADCValueArrived(double newValue);
private event NewADCValueArrived newAdcValue;
private double getADCValueDirectly()
{
double value = -1;
NewADCValueArrived handler = delegate(double newValue)
{
value = newValue;
};
newAdcValue += handler;
askFornewValues(); //Fire and forget
timeout = 0;
while(value != -1 && timeout <100)
{
timeout++;
Thread.sleep(1); //Want to avoid this!! because sleeping for 1 ms is very inaccurate
}
newAdcValue -= handler;
if (value != -1)
{
return value;
}
else
{
throw Exception("Timeout");
}
}
}
公共类信息
{
公共委托void NewADCValueArrived(双newValue);
私有事件newAdcValue到达newAdcValue;
私有双getadcvaluedirective()
{
双值=-1;
NewADCValueArrived handler=委托(双newValue)
{
值=新值;
};
newAdcValue+=处理程序;
askFornewValues();//触发并忘记
超时=0;
while(value!=-1&&timeout您可以使用TaskCompletionSource
将事件抽象为任务
。您可以参考如何操作。您甚至不需要参考答案;问题本身显示了如何操作
一旦你得到了任务
你就不必再投票了。你可以做各种有趣的事情,比如等待
,继续
,甚至等待
对于超时,您可以使用带有计时器的callTaskCompletionSource.setcancelled
关于如何取消订阅活动:(在评论中询问)
公共类MyClass
{
完成公共事件行动;
}
公共静态任务FromEvent(MyClass obj)
{
TaskCompletionSource tcs=新的TaskCompletionSource();
动作完成=空;
完成=()=>
{
tcs.SetResult(空);
obj.OnCompletion-=完成;
};
obj.OnCompletion+=完成;
返回tcs.Task;
}
您可以使用TaskCompletionSource
将事件抽象为任务
。您可以参考如何操作。您甚至不需要参考答案;问题本身显示了如何操作
一旦你得到了任务
你就不必再投票了。你可以做各种有趣的事情,比如等待
,继续
,甚至等待
对于超时,您可以使用带有计时器的callTaskCompletionSource.setcancelled
关于如何取消订阅活动:(在评论中询问)
公共类MyClass
{
完成公共事件行动;
}
公共静态任务FromEvent(MyClass obj)
{
TaskCompletionSource tcs=新的TaskCompletionSource();
动作完成=空;
完成=()=>
{
tcs.SetResult(空);
obj.OnCompletion-=完成;
};
obj.OnCompletion+=完成;
返回tcs.Task;
}
如果您有选择,我可能会选择基于任务的解决方案
否则,您可以设置一个AutoResetEvent并等待事件处理程序触发它
private double getADCValueDirectly()
{
double value = -1;
AutoResetEvent eventCompleted = new AutoResetEvent(false);
NewADCValueArrived handler = delegate(double newValue)
{
value = newValue;
// signal the waithandle
eventCompleted.Set();
};
newAdcValue += handler;
askFornewValues(); //Fire and forget
eventCompleted.WaitOne(); // optionally enter a timeout here
newAdcValue -= handler;
if (value != -1)
{
return value;
}
else
{
throw Exception("Timeout");
}
}
在上有一篇关于C#线程处理的优秀教程,如果你有选择的话,我可能会选择基于任务的解决方案
否则,您可以设置一个AutoResetEvent并等待事件处理程序触发它
private double getADCValueDirectly()
{
double value = -1;
AutoResetEvent eventCompleted = new AutoResetEvent(false);
NewADCValueArrived handler = delegate(double newValue)
{
value = newValue;
// signal the waithandle
eventCompleted.Set();
};
newAdcValue += handler;
askFornewValues(); //Fire and forget
eventCompleted.WaitOne(); // optionally enter a timeout here
newAdcValue -= handler;
if (value != -1)
{
return value;
}
else
{
throw Exception("Timeout");
}
}
在上有一个关于C#线程处理的优秀教程,如果它真的是实时的,并且您负担不起让调度程序采取行动,那么您可以进行忙碌的等待:
timeout=0;
而(value!=-1&&timeout如果它真的是实时的,并且您负担不起让调度器采取行动,那么您可以进行繁忙的等待:
timeout=0;
而(value!=-1&&timeout100000*100
繁忙等待的迭代次数?您可能只是为了等待而计划烧掉cpu?在1Ghz cpu上,这将需要100k*100=10M周期==100ms(实际需要的数字会有所不同…)100000*100
busy wait的迭代次数?您可能只是为了等待而计划烧掉cpu?在1Ghz的cpu上,这将需要100k*100=10M周期==100ms(实际需要的数字会有所不同…),感谢您的解决方案。链接页面上有一个问题:每次我调用FromEvent()函数在事件中添加了一个新函数。我是否必须在事后删除此函数,还是垃圾收集器为我执行此操作。在我的情况下,此函数可以经常调用。感谢您的解决方案。链接页面上有一个问题:每次我调用FromEvent()时函数在事件中添加了一个新函数。我是否必须在事后删除此函数,或者垃圾收集器是否为我执行此操作。在我的情况下,可以经常调用此函数。
timeout = 0;
while(value != -1 && timeout <100000)
{
timeout++;
for(int j= 0; j < 100; j++); // keep CPU busy
}