有没有办法唤醒正在睡觉的线程?

发布于 2024-09-14 02:19:03 字数 48 浏览 2 评论 0原文

C# 有没有办法唤醒休眠线程?那么,是否让它休眠很长时间并在需要处理工作时唤醒它?

Is there a way to wake a sleeping thread in C#? So, have it sleep for either a long time and wake it when you want work processed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

日裸衫吸 2024-09-21 02:19:03

AutoResetEvent 对象(或另一个 WaitHandle 实现)可用于休眠,直到收到另一个线程的信号:

// launch a calculation thread
var waitHandle = new AutoResetEvent(false);
int result;
var calculationThread = new Thread(
    delegate
    {
        // this code will run on the calculation thread
        result = FactorSomeLargeNumber();
        waitHandle.Set();
    });
calculationThread.Start();

// now that the other thread is launched, we can do something else.
DoOtherStuff();

// we've run out of other stuff to do, so sleep until calculation thread finishes
waitHandle.WaitOne();

An AutoResetEvent object (or another WaitHandle implementation) can be used to sleep until a signal from another thread is received:

// launch a calculation thread
var waitHandle = new AutoResetEvent(false);
int result;
var calculationThread = new Thread(
    delegate
    {
        // this code will run on the calculation thread
        result = FactorSomeLargeNumber();
        waitHandle.Set();
    });
calculationThread.Start();

// now that the other thread is launched, we can do something else.
DoOtherStuff();

// we've run out of other stuff to do, so sleep until calculation thread finishes
waitHandle.WaitOne();
顾忌 2024-09-21 02:19:03

如果您的线程处于对 Sleep 的调用中,那么(通常)没有办法唤醒它。 (我知道的唯一例外是Java,如果其他线程调用thread.interrupt(),它允许提前结束睡眠。)

您正在讨论的模式似乎调用对于事件:线程包含一个循环,在循环顶部等待事件触发。如果当前未设置该事件,则该线程将“休眠”,直到其他线程触发该事件。此时,休眠线程被唤醒并继续其工作,直到下一次循环时它休眠以等待另一个事件。

If your thread is inside a call to Sleep, then there isn't (usually) a way to wake it up. (The only exception I'm aware of is Java, which allows a sleep to be ended early if some other thread calls thread.interrupt().)

The pattern that you're talking about seems to call for an event: the thread contains a loop, at the top of which it waits for an event to fire. If the event is currently unset, then the thread "sleeps" until some other thread fires the event. At that point, the sleeping thread wakes up and continues its work, until the next time through the loop when it sleeps to wait for another event.

内心荒芜 2024-09-21 02:19:03

实际上有一个 线程。 C# 中的 Interrupt() 方法。
虽然接受的答案确实描述了您在您的情况下可能需要的良好模式,但我来到这个问题寻找 Thread.Interrupt 所以我把它放在这里。

There is actually a thread.Interrupt() method in C#.
While the accepted answer does describes a good pattern that you probably want in your case, I came to this question looking for Thread.Interrupt so I am putting it here.

金橙橙 2024-09-21 02:19:03

最好的解决方案是将 Task 对象与默认的 TaskFactory 一起使用。这个 API(在 .NET 4.0 中引入)使用带有工作窃取队列和所有奇特东西的线程池。

如果 .NET 4.0 不可用,则使用 ThreadPool,它具有内置工作队列(它执行一些池平衡,但与 4.0 线程池不在同一范围内)。

如果您确实必须自己动手,那么我推荐使用 BlockingCollection,它是 .NET 4.0 中添加的阻塞消费者/生产者队列。

如果您确实必须自己执行此操作并且无法使用 .NET 4.0,那么您可以使用 ManualResetEventAutoResetEvent 以及受保护的工作队列。

The best solution would be to use Task objects with the default TaskFactory. This API (introduced in .NET 4.0) uses a pool of threads with work-stealing queues and all that fancy stuff.

If .NET 4.0 isn't available, then use the ThreadPool, which has a built-in work queue (which does some pool balancing but not on the same scope as the 4.0 thread pool).

If you really must do it yourself, then I recommend a BlockingCollection<T>, which is a blocking consumer/producer queue added in .NET 4.0.

If you really must do it yourself and can't use .NET 4.0, then you can use a ManualResetEvent or AutoResetEvent along with a lock-protected queue of work.

2024-09-21 02:19:03

扩展 Wim 的答案,您还可以指定 WaitHandle.WaitOne() 调用的超时。因此您可以使用 Thread.Sleep() 来代替。 CancellationToken 结构为您提供了一个,这样您就可以像这样发出任务信号:

string SleepAndWakeUp(string value,CancellationToken ct)
{
    ct.WaitHandle.WaitOne(60000);
    return value;
}

void Parent()
{
     CancellationTokenSource cts = new CancellationTokenSource();
     Task.Run(() => SleepAndWakeUp("Hello World!", cts.Token), cts.Token);
     //Do some other work here
     cts.Cancel(); //Wake up the asynch task
}

Expanding Wim's answer you can also specify a timeout for the WaitHandle.WaitOne() call. So you can use instead of Thread.Sleep(). CancellationToken struct provides you with one so you can signal your tasks like this:

string SleepAndWakeUp(string value,CancellationToken ct)
{
    ct.WaitHandle.WaitOne(60000);
    return value;
}

void Parent()
{
     CancellationTokenSource cts = new CancellationTokenSource();
     Task.Run(() => SleepAndWakeUp("Hello World!", cts.Token), cts.Token);
     //Do some other work here
     cts.Cancel(); //Wake up the asynch task
}
谁把谁当真 2024-09-21 02:19:03

这个 线程帮助? C# 具有用于线程事件处理的良好的功能。我的大部分工作都是在 Python 中完成的,但 C# 似乎有可靠的线程阻塞库。

Would this thread help? C# has good functionality for thread Event handling. I've done most of my work in Python, but C# seems to have solid libraries for thread blocking.

嘿哥们儿 2024-09-21 02:19:03

基于 Ilia 的建议:

t1 = new Thread(() =>
    {
     while (keepRunning) {
         try {
             DoWork();
             Thread.Sleep(all_night_long);
             }
         catch (ThreadInterruptedException) { }
         }
    });
t1.Start();

并且...

public void WakeUp()
{
   t1.Interrupt();
}

public void StopRunningImmediately()
{
   keepRunning = false;
   WakeUp(); //immediately
}

这个解决方案很粗糙,因为可能还有其他原因引发 ThreadInterruptedException 。

Based on Ilia's suggestion:

t1 = new Thread(() =>
    {
     while (keepRunning) {
         try {
             DoWork();
             Thread.Sleep(all_night_long);
             }
         catch (ThreadInterruptedException) { }
         }
    });
t1.Start();

and...

public void WakeUp()
{
   t1.Interrupt();
}

public void StopRunningImmediately()
{
   keepRunning = false;
   WakeUp(); //immediately
}

This solution is crude, as there may be other reasons why the ThreadInterruptedException is thrown.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文