gpt4 book ai didi

c# - RegisterWaitForSingleObject 未定义行为与 ManualResetEvent

转载 作者:太空狗 更新时间:2023-10-30 00:38:53 32 4
gpt4 key购买 nike

在我的一个项目中,我需要安排一项任务在后台线程中的某个指定时间间隔后完成。我使用 ThreadPool.RegisterWaitForSingleObject 机制来做到这一点。根据文档,第一个参数可能是 WaitHandle,它有许多子类。起初我更喜欢 ManualResetEvent;我使用这个事件来发出完成时间表和退出的信号。这是我的代码:

public class ScheduleTester
{
private long m_LastTicks;
private RegisteredWaitHandle m_RegisterWaitHandle;
public ManualResetEvent Event;

public ScheduleTester()
{
Event = new ManualResetEvent(false);
m_RegisterWaitHandle = ThreadPool.RegisterWaitForSingleObject(Event, new WaitOrTimerCallback(WaitOrTimerCallback), null, 500, false);
m_LastTicks = DateTime.Now.Ticks;
}

private void WaitOrTimerCallback(object state, bool timedOut)
{
long ticks = DateTime.Now.Ticks;

if (timedOut)
{
Console.WriteLine(string.Format("Timeout : {0} ... Do scheduled job takes 1 seconds long, Thread ID : {1}", (ticks - m_LastTicks) / 10000f, Thread.CurrentThread.GetHashCode()));
}
else
{
Console.WriteLine(string.Format("Signaled....Unregister , Thread ID : {0}", Thread.CurrentThread.GetHashCode()));

if (null != m_RegisterWaitHandle)
m_RegisterWaitHandle.Unregister(null);
}

m_LastTicks = ticks;
}
}

static void Main()
{
ScheduleTester waitFor = new ScheduleTester();
Console.ReadKey();
waitFor.Event.Set();
Console.ReadKey();
}

我期望的是看到很多行通知预定的工作已经完成,直到我按下一个键来发出事件信号并且一行通知预定的完成。但我看到的是: output1

ManualResetEvent 替换为 AutoResetEvent 时,一切都很好。 output2

最佳答案

是的,这不是非常直观的行为。您可以从调试器的“调试”>“Windows”>“线程”窗口轻松查看潜在问题。您会看到大量 tp 线程都在执行您的 WaitOrTimerCallback() 方法。

阻止这种情况发生的责任在于你。 RWFSO 的executeOnlyOnce 参数非常非常重要。您现在传递了 false,这使得您等待的同步对象只收到一次信号非常重要。就像 AutoResetEvent 一样。

如果您使用 ManualResetEvent,那么您必须传递 true。并将您的回调调整为:

private void WaitOrTimerCallback(object state, bool timedOut) {
long ticks = DateTime.Now.Ticks;
if (timedOut) {
Console.WriteLine(string.Format("Timeout : {0} ... Do scheduled job takes 1 seconds long, Thread ID : {1}", (ticks - m_LastTicks) / 10000f, Thread.CurrentThread.ManagedThreadId));
ThreadPool.RegisterWaitForSingleObject(Event, new WaitOrTimerCallback(WaitOrTimerCallback), null, 500, true);
}
else {
Console.WriteLine(string.Format("Signaled....Unregister , Thread ID : {0}", Thread.CurrentThread.ManagedThreadId));
m_RegisterWaitHandle.Unregister(null);
}
m_LastTicks = ticks;
}

您现在将看到它在等待间隔检测超时。不确定这是不是故意的。

关于c# - RegisterWaitForSingleObject 未定义行为与 ManualResetEvent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37482869/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com